Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions src/objdictgen/__main__.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -149,6 +149,7 @@ def main(debugopts: DebugOpts, args: Sequence[str]|None = None):
""", aliases=['compare'])
subp.add_argument('od1', help="Object dictionary")
subp.add_argument('od2', help="Object dictionary")
subp.add_argument('-v', '--verbose', action="count", default=0, help="Verbose output (can be used multiple times)")
subp.add_argument('--show', action="store_true", help="Show difference data")
subp.add_argument('--internal', action="store_true", help="Diff internal object")
subp.add_argument('--data', action="store_true", help="Show difference as data")
Expand All@@ -166,9 +167,7 @@ def main(debugopts: DebugOpts, args: Sequence[str]|None = None):
""", aliases=['cat'])
subp.add_argument('od', nargs="+", help="Object dictionary")
subp.add_argument('-i', '--index', action="append", help="Specify parameter index to show")
subp.add_argument('--all', action="store_true",
help="Show all subindexes, including subindex 0")
subp.add_argument('--compact', action="store_true", help="Compact listing")
subp.add_argument('-v', '--verbose', action="count", default=0, help="Verbose output (can be used multiple times)")
subp.add_argument('--raw', action="store_true", help="Show raw parameter values")
subp.add_argument('--short', action="store_true", help="Do not list sub-index")
subp.add_argument('--unused', action="store_true", help="Include unused profile parameters")
Expand DownExpand Up@@ -276,7 +275,7 @@ def main(debugopts: DebugOpts, args: Sequence[str]|None = None):
od2 = open_od(opts.od2, validate=not opts.novalidate)

lines = list(format_diff_nodes(od1, od2, data=opts.data, raw=opts.raw,
internal=opts.internal, show=opts.show))
internal=opts.internal, show=opts.show, verbose=opts.verbose))

for line in lines:
print(line)
Expand Down
59 changes: 32 additions & 27 deletions src/objdictgen/printing.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -18,10 +18,9 @@
@dataclass
class FormatNodeOpts:
""" Options for formatting the node """
compact: bool = False
verbose: int = 0
short: bool = False
unused: bool = False
all: bool = False
raw: bool = False
internal: bool = False

Expand DownExpand Up@@ -78,25 +77,26 @@ def format_node(
extra = f"{pname} (not loaded)"
profiles.append(extra)

if not kwargs.get("compact"):
yield f"{Fore.CYAN}File:{Style.RESET_ALL} {name}"
yield f"{Fore.CYAN}Name:{Style.RESET_ALL} {node.Name} [{node.Type.upper()}] {node.Description}"
yield f"{Fore.CYAN}File:{Style.RESET_ALL} {name}"
yield f"{Fore.CYAN}Name:{Style.RESET_ALL} {node.Name} [{node.Type.upper()}] {node.Description}"
if opts.verbose:
tp = ", ".join(profiles) or None
yield f"{Fore.CYAN}Profiles:{Style.RESET_ALL} {tp}"
if node.ID:
yield f"{Fore.CYAN}ID:{Style.RESET_ALL} {node.ID}"
yield ""
if node.ID:
yield f"{Fore.CYAN}ID:{Style.RESET_ALL} {node.ID}"
yield ""

index_range = None
header = ''
last_is_equal = False

for k in keys:

# Get the index range title
ir = maps.INDEX_RANGES.get_index_range(k)
if index_range != ir:
index_range = ir
if not opts.compact:
if opts.verbose:
header = Fore.YELLOW + ir.description + Style.RESET_ALL

obj = node.GetIndexEntry(k)
Expand All@@ -107,14 +107,19 @@ def format_node(
if obj == minusobj:
linegen = format_od_object(node, k, short=True)
lines = [remove_color(line) for line in linegen]
lines[0] = Fore.LIGHTBLACK_EX + lines[0] + f" {Fore.LIGHTRED_EX}<EQUAL>{Style.RESET_ALL}"
pre = " " if opts.verbose else ''
lines[0] = f"{pre}{Fore.LIGHTBLACK_EX}{lines[0]} {Fore.GREEN}<EQUAL>{Style.RESET_ALL}"
yield from lines
last_is_equal = True
continue

if last_is_equal and opts.verbose:
yield ""

# Yield the text for the index
lines = list(format_od_object(
node, k, short=opts.short, compact=opts.compact, unused=opts.unused,
verbose=opts.all, raw=opts.raw
node, k, short=opts.short, verbose=opts.verbose, unused=opts.unused,
raw=opts.raw
))

if opts.internal and lines[-1] == "":
Expand All@@ -133,12 +138,12 @@ def format_node(
obj = node.GetIndexEntry(k)
lines = pformat(obj, width=TERM_COLS).splitlines()
yield from lines
if not opts.compact:
if opts.verbose:
yield ""


def format_od_header(
node: Node, index: int, *, unused=False, compact=False, raw=False,
node: Node, index: int, *, unused=False, verbose=False, raw=False,
entry: TIndexEntry|None = None
) -> tuple[str, dict[str, str]]:
"""Get the print output for a dictionary entry header"""
Expand DownExpand Up@@ -194,13 +199,13 @@ def format_od_header(
'name': f"{Fore.LIGHTWHITE_EX}{t_name}{Style.RESET_ALL}",
'struct': f"{Fore.LIGHTYELLOW_EX}[{t_string.upper()}]{Style.RESET_ALL}",
'flags': f" {Fore.MAGENTA}{t_flags}{Style.RESET_ALL}" if flags else '',
'pre': ' ' if not compact else '',
'pre': ' ' if verbose else '',
}


def format_od_object(
node: Node, index: int, *, short=False, compact=False,
unused=False, verbose=False, raw=False,
node: Node, index: int, *, short=False,
unused=False, verbose: int=0, raw=False,
widths: dict[str, int]|None = None
) -> Generator[str, None, None]:
"""Return the print formatting for an object dictionary entry."""
Expand All@@ -211,7 +216,7 @@ def format_od_object(

# Get the header for the entry and output it unless it is empty
line, fields = format_od_header(
node, index, unused=unused, compact=compact, entry=param, raw=raw
node, index, unused=unused, verbose=verbose, entry=param, raw=raw
)
if not line:
return
Expand DownExpand Up@@ -292,7 +297,7 @@ def format_od_object(
t_comment = f"{Fore.LIGHTBLACK_EX}/* {t_comment} */{Style.RESET_ALL}"

# Omit printing the first element unless specifically requested
if (not verbose and i == 0
if (verbose < 2 and i == 0
and obj['struct'] & OD.MultipleSubindexes
and not t_comment
):
Expand DownExpand Up@@ -335,20 +340,20 @@ def format_od_object(
for infoentry in infos:
yield fmt.format(**infoentry)

if not compact and infos:
if verbose and infos:
yield ""


def format_diff_nodes(
od1: Node, od2: Node, *, data=False, raw=False,
od1: Node, od2: Node, *, data=False, raw=False, verbose: int=0,
internal=False, show=False
) -> Generator[str, None, None]:
""" Compare two object dictionaries and return the formatted differences. """

if internal or data:
diffs = jsonod.diff(od1, od2, internal=internal)
else:
diffs = text_diff(od1, od2, data_mode=raw)
diffs = text_diff(od1, od2, data_mode=raw, verbose=verbose)

rst = Style.RESET_ALL

Expand DownExpand Up@@ -413,7 +418,7 @@ def _pprint(text: str, prefix: str = ' '):
yield f"{Fore.RED}{chtype} {ppath} {change}{rst}"


def text_diff(od1: Node, od2: Node, data_mode: bool=False) -> TDiffNodes:
def text_diff(od1: Node, od2: Node, data_mode: bool=False, verbose: int=0) -> TDiffNodes:
""" Compare two object dictionaries as text and return the differences. """

# Get all indices for the nodes
Expand All@@ -433,15 +438,15 @@ def text_diff(od1: Node, od2: Node, data_mode: bool=False) -> TDiffNodes:
# Run through the formatting to get the width for the columns
widths: dict[str, int] = {}
if index in keys1:
list(format_od_object(od1, index, unused=True, widths=widths))
list(format_od_object(od1, index, unused=True, verbose=verbose, widths=widths))
if index in keys2:
list(format_od_object(od2, index, unused=True, widths=widths))
list(format_od_object(od2, index, unused=True, verbose=verbose, widths=widths))

if index in keys1:
text1 = list(format_od_object(od1, index, unused=True, widths=widths))
text1 = list(format_od_object(od1, index, unused=True, verbose=verbose, widths=widths))
entry1 = od1.GetIndexEntry(index)
if index in keys2:
text2 = list(format_od_object(od2, index, unused=True, widths=widths))
text2 = list(format_od_object(od2, index, unused=True, verbose=verbose, widths=widths))
entry2 = od2.GetIndexEntry(index)

if data_mode:
Expand Down
6 changes: 3 additions & 3 deletions tests/test_printing.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -18,7 +18,7 @@ def test_printing_format_node(odpath, file):
od.ID = 1

opts = FormatNodeOpts(
compact=False, short=False, unused=True, all=True, raw=False
verbose=True, short=False, unused=True, raw=False
)

lines = format_node(od, file, opts=opts)
Expand All@@ -27,7 +27,7 @@ def test_printing_format_node(odpath, file):
assert isinstance(line, str)

opts = FormatNodeOpts(
compact=False, short=False, unused=True, all=True, raw=False
verbose=True, short=False, unused=True, raw=False
)

lines = format_node(od, file, index=[0x1000], opts=opts)
Expand All@@ -36,7 +36,7 @@ def test_printing_format_node(odpath, file):
assert isinstance(line, str)

opts = FormatNodeOpts(
compact=False, short=False, unused=True, all=True, raw=False
verbose=True, short=False, unused=True, raw=False
)

with pytest.raises(ValueError) as exc:
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions src/objdictgen/__main__.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -149,6 +149,7 @@ def main(debugopts: DebugOpts, args: Sequence[str]|None = None):
""", aliases=['compare'])
subp.add_argument('od1', help="Object dictionary")
subp.add_argument('od2', help="Object dictionary")
subp.add_argument('-v', '--verbose', action="count", default=0, help="Verbose output (can be used multiple times)")
subp.add_argument('--show', action="store_true", help="Show difference data")
subp.add_argument('--internal', action="store_true", help="Diff internal object")
subp.add_argument('--data', action="store_true", help="Show difference as data")
Expand All@@ -166,9 +167,7 @@ def main(debugopts: DebugOpts, args: Sequence[str]|None = None):
""", aliases=['cat'])
subp.add_argument('od', nargs="+", help="Object dictionary")
subp.add_argument('-i', '--index', action="append", help="Specify parameter index to show")
subp.add_argument('--all', action="store_true",
help="Show all subindexes, including subindex 0")
subp.add_argument('--compact', action="store_true", help="Compact listing")
subp.add_argument('-v', '--verbose', action="count", default=0, help="Verbose output (can be used multiple times)")
subp.add_argument('--raw', action="store_true", help="Show raw parameter values")
subp.add_argument('--short', action="store_true", help="Do not list sub-index")
subp.add_argument('--unused', action="store_true", help="Include unused profile parameters")
Expand DownExpand Up@@ -276,7 +275,7 @@ def main(debugopts: DebugOpts, args: Sequence[str]|None = None):
od2 = open_od(opts.od2, validate=not opts.novalidate)

lines = list(format_diff_nodes(od1, od2, data=opts.data, raw=opts.raw,
internal=opts.internal, show=opts.show))
internal=opts.internal, show=opts.show, verbose=opts.verbose))

for line in lines:
print(line)
Expand Down
59 changes: 32 additions & 27 deletions src/objdictgen/printing.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -18,10 +18,9 @@
@dataclass
class FormatNodeOpts:
""" Options for formatting the node """
compact: bool = False
verbose: int = 0
short: bool = False
unused: bool = False
all: bool = False
raw: bool = False
internal: bool = False

Expand DownExpand Up@@ -78,25 +77,26 @@ def format_node(
extra = f"{pname} (not loaded)"
profiles.append(extra)

if not kwargs.get("compact"):
yield f"{Fore.CYAN}File:{Style.RESET_ALL} {name}"
yield f"{Fore.CYAN}Name:{Style.RESET_ALL} {node.Name} [{node.Type.upper()}] {node.Description}"
yield f"{Fore.CYAN}File:{Style.RESET_ALL} {name}"
yield f"{Fore.CYAN}Name:{Style.RESET_ALL} {node.Name} [{node.Type.upper()}] {node.Description}"
if opts.verbose:
tp = ", ".join(profiles) or None
yield f"{Fore.CYAN}Profiles:{Style.RESET_ALL} {tp}"
if node.ID:
yield f"{Fore.CYAN}ID:{Style.RESET_ALL} {node.ID}"
yield ""
if node.ID:
yield f"{Fore.CYAN}ID:{Style.RESET_ALL} {node.ID}"
yield ""

index_range = None
header = ''
last_is_equal = False

for k in keys:

# Get the index range title
ir = maps.INDEX_RANGES.get_index_range(k)
if index_range != ir:
index_range = ir
if not opts.compact:
if opts.verbose:
header = Fore.YELLOW + ir.description + Style.RESET_ALL

obj = node.GetIndexEntry(k)
Expand All@@ -107,14 +107,19 @@ def format_node(
if obj == minusobj:
linegen = format_od_object(node, k, short=True)
lines = [remove_color(line) for line in linegen]
lines[0] = Fore.LIGHTBLACK_EX + lines[0] + f" {Fore.LIGHTRED_EX}<EQUAL>{Style.RESET_ALL}"
pre = " " if opts.verbose else ''
lines[0] = f"{pre}{Fore.LIGHTBLACK_EX}{lines[0]} {Fore.GREEN}<EQUAL>{Style.RESET_ALL}"
yield from lines
last_is_equal = True
continue

if last_is_equal and opts.verbose:
yield ""

# Yield the text for the index
lines = list(format_od_object(
node, k, short=opts.short, compact=opts.compact, unused=opts.unused,
verbose=opts.all, raw=opts.raw
node, k, short=opts.short, verbose=opts.verbose, unused=opts.unused,
raw=opts.raw
))

if opts.internal and lines[-1] == "":
Expand All@@ -133,12 +138,12 @@ def format_node(
obj = node.GetIndexEntry(k)
lines = pformat(obj, width=TERM_COLS).splitlines()
yield from lines
if not opts.compact:
if opts.verbose:
yield ""


def format_od_header(
node: Node, index: int, *, unused=False, compact=False, raw=False,
node: Node, index: int, *, unused=False, verbose=False, raw=False,
entry: TIndexEntry|None = None
) -> tuple[str, dict[str, str]]:
"""Get the print output for a dictionary entry header"""
Expand DownExpand Up@@ -194,13 +199,13 @@ def format_od_header(
'name': f"{Fore.LIGHTWHITE_EX}{t_name}{Style.RESET_ALL}",
'struct': f"{Fore.LIGHTYELLOW_EX}[{t_string.upper()}]{Style.RESET_ALL}",
'flags': f" {Fore.MAGENTA}{t_flags}{Style.RESET_ALL}" if flags else '',
'pre': ' ' if not compact else '',
'pre': ' ' if verbose else '',
}


def format_od_object(
node: Node, index: int, *, short=False, compact=False,
unused=False, verbose=False, raw=False,
node: Node, index: int, *, short=False,
unused=False, verbose: int=0, raw=False,
widths: dict[str, int]|None = None
) -> Generator[str, None, None]:
"""Return the print formatting for an object dictionary entry."""
Expand All@@ -211,7 +216,7 @@ def format_od_object(

# Get the header for the entry and output it unless it is empty
line, fields = format_od_header(
node, index, unused=unused, compact=compact, entry=param, raw=raw
node, index, unused=unused, verbose=verbose, entry=param, raw=raw
)
if not line:
return
Expand DownExpand Up@@ -292,7 +297,7 @@ def format_od_object(
t_comment = f"{Fore.LIGHTBLACK_EX}/* {t_comment} */{Style.RESET_ALL}"

# Omit printing the first element unless specifically requested
if (not verbose and i == 0
if (verbose < 2 and i == 0
and obj['struct'] & OD.MultipleSubindexes
and not t_comment
):
Expand DownExpand Up@@ -335,20 +340,20 @@ def format_od_object(
for infoentry in infos:
yield fmt.format(**infoentry)

if not compact and infos:
if verbose and infos:
yield ""


def format_diff_nodes(
od1: Node, od2: Node, *, data=False, raw=False,
od1: Node, od2: Node, *, data=False, raw=False, verbose: int=0,
internal=False, show=False
) -> Generator[str, None, None]:
""" Compare two object dictionaries and return the formatted differences. """

if internal or data:
diffs = jsonod.diff(od1, od2, internal=internal)
else:
diffs = text_diff(od1, od2, data_mode=raw)
diffs = text_diff(od1, od2, data_mode=raw, verbose=verbose)

rst = Style.RESET_ALL

Expand DownExpand Up@@ -413,7 +418,7 @@ def _pprint(text: str, prefix: str = ' '):
yield f"{Fore.RED}{chtype} {ppath} {change}{rst}"


def text_diff(od1: Node, od2: Node, data_mode: bool=False) -> TDiffNodes:
def text_diff(od1: Node, od2: Node, data_mode: bool=False, verbose: int=0) -> TDiffNodes:
""" Compare two object dictionaries as text and return the differences. """

# Get all indices for the nodes
Expand All@@ -433,15 +438,15 @@ def text_diff(od1: Node, od2: Node, data_mode: bool=False) -> TDiffNodes:
# Run through the formatting to get the width for the columns
widths: dict[str, int] = {}
if index in keys1:
list(format_od_object(od1, index, unused=True, widths=widths))
list(format_od_object(od1, index, unused=True, verbose=verbose, widths=widths))
if index in keys2:
list(format_od_object(od2, index, unused=True, widths=widths))
list(format_od_object(od2, index, unused=True, verbose=verbose, widths=widths))

if index in keys1:
text1 = list(format_od_object(od1, index, unused=True, widths=widths))
text1 = list(format_od_object(od1, index, unused=True, verbose=verbose, widths=widths))
entry1 = od1.GetIndexEntry(index)
if index in keys2:
text2 = list(format_od_object(od2, index, unused=True, widths=widths))
text2 = list(format_od_object(od2, index, unused=True, verbose=verbose, widths=widths))
entry2 = od2.GetIndexEntry(index)

if data_mode:
Expand Down
6 changes: 3 additions & 3 deletions tests/test_printing.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -18,7 +18,7 @@ def test_printing_format_node(odpath, file):
od.ID = 1

opts = FormatNodeOpts(
compact=False, short=False, unused=True, all=True, raw=False
verbose=True, short=False, unused=True, raw=False
)

lines = format_node(od, file, opts=opts)
Expand All@@ -27,7 +27,7 @@ def test_printing_format_node(odpath, file):
assert isinstance(line, str)

opts = FormatNodeOpts(
compact=False, short=False, unused=True, all=True, raw=False
verbose=True, short=False, unused=True, raw=False
)

lines = format_node(od, file, index=[0x1000], opts=opts)
Expand All@@ -36,7 +36,7 @@ def test_printing_format_node(odpath, file):
assert isinstance(line, str)

opts = FormatNodeOpts(
compact=False, short=False, unused=True, all=True, raw=False
verbose=True, short=False, unused=True, raw=False
)

with pytest.raises(ValueError) as exc:
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions src/objdictgen/__main__.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -149,6 +149,7 @@ def main(debugopts: DebugOpts, args: Sequence[str]|None = None):
""", aliases=['compare'])
subp.add_argument('od1', help="Object dictionary")
subp.add_argument('od2', help="Object dictionary")
subp.add_argument('-v', '--verbose', action="count", default=0, help="Verbose output (can be used multiple times)")
subp.add_argument('--show', action="store_true", help="Show difference data")
subp.add_argument('--internal', action="store_true", help="Diff internal object")
subp.add_argument('--data', action="store_true", help="Show difference as data")
Expand All@@ -166,9 +167,7 @@ def main(debugopts: DebugOpts, args: Sequence[str]|None = None):
""", aliases=['cat'])
subp.add_argument('od', nargs="+", help="Object dictionary")
subp.add_argument('-i', '--index', action="append", help="Specify parameter index to show")
subp.add_argument('--all', action="store_true",
help="Show all subindexes, including subindex 0")
subp.add_argument('--compact', action="store_true", help="Compact listing")
subp.add_argument('-v', '--verbose', action="count", default=0, help="Verbose output (can be used multiple times)")
subp.add_argument('--raw', action="store_true", help="Show raw parameter values")
subp.add_argument('--short', action="store_true", help="Do not list sub-index")
subp.add_argument('--unused', action="store_true", help="Include unused profile parameters")
Expand DownExpand Up@@ -276,7 +275,7 @@ def main(debugopts: DebugOpts, args: Sequence[str]|None = None):
od2 = open_od(opts.od2, validate=not opts.novalidate)

lines = list(format_diff_nodes(od1, od2, data=opts.data, raw=opts.raw,
internal=opts.internal, show=opts.show))
internal=opts.internal, show=opts.show, verbose=opts.verbose))

for line in lines:
print(line)
Expand Down
59 changes: 32 additions & 27 deletions src/objdictgen/printing.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -18,10 +18,9 @@
@dataclass
class FormatNodeOpts:
""" Options for formatting the node """
compact: bool = False
verbose: int = 0
short: bool = False
unused: bool = False
all: bool = False
raw: bool = False
internal: bool = False

Expand DownExpand Up@@ -78,25 +77,26 @@ def format_node(
extra = f"{pname} (not loaded)"
profiles.append(extra)

if not kwargs.get("compact"):
yield f"{Fore.CYAN}File:{Style.RESET_ALL} {name}"
yield f"{Fore.CYAN}Name:{Style.RESET_ALL} {node.Name} [{node.Type.upper()}] {node.Description}"
yield f"{Fore.CYAN}File:{Style.RESET_ALL} {name}"
yield f"{Fore.CYAN}Name:{Style.RESET_ALL} {node.Name} [{node.Type.upper()}] {node.Description}"
if opts.verbose:
tp = ", ".join(profiles) or None
yield f"{Fore.CYAN}Profiles:{Style.RESET_ALL} {tp}"
if node.ID:
yield f"{Fore.CYAN}ID:{Style.RESET_ALL} {node.ID}"
yield ""
if node.ID:
yield f"{Fore.CYAN}ID:{Style.RESET_ALL} {node.ID}"
yield ""

index_range = None
header = ''
last_is_equal = False

for k in keys:

# Get the index range title
ir = maps.INDEX_RANGES.get_index_range(k)
if index_range != ir:
index_range = ir
if not opts.compact:
if opts.verbose:
header = Fore.YELLOW + ir.description + Style.RESET_ALL

obj = node.GetIndexEntry(k)
Expand All@@ -107,14 +107,19 @@ def format_node(
if obj == minusobj:
linegen = format_od_object(node, k, short=True)
lines = [remove_color(line) for line in linegen]
lines[0] = Fore.LIGHTBLACK_EX + lines[0] + f" {Fore.LIGHTRED_EX}<EQUAL>{Style.RESET_ALL}"
pre = " " if opts.verbose else ''
lines[0] = f"{pre}{Fore.LIGHTBLACK_EX}{lines[0]} {Fore.GREEN}<EQUAL>{Style.RESET_ALL}"
yield from lines
last_is_equal = True
continue

if last_is_equal and opts.verbose:
yield ""

# Yield the text for the index
lines = list(format_od_object(
node, k, short=opts.short, compact=opts.compact, unused=opts.unused,
verbose=opts.all, raw=opts.raw
node, k, short=opts.short, verbose=opts.verbose, unused=opts.unused,
raw=opts.raw
))

if opts.internal and lines[-1] == "":
Expand All@@ -133,12 +138,12 @@ def format_node(
obj = node.GetIndexEntry(k)
lines = pformat(obj, width=TERM_COLS).splitlines()
yield from lines
if not opts.compact:
if opts.verbose:
yield ""


def format_od_header(
node: Node, index: int, *, unused=False, compact=False, raw=False,
node: Node, index: int, *, unused=False, verbose=False, raw=False,
entry: TIndexEntry|None = None
) -> tuple[str, dict[str, str]]:
"""Get the print output for a dictionary entry header"""
Expand DownExpand Up@@ -194,13 +199,13 @@ def format_od_header(
'name': f"{Fore.LIGHTWHITE_EX}{t_name}{Style.RESET_ALL}",
'struct': f"{Fore.LIGHTYELLOW_EX}[{t_string.upper()}]{Style.RESET_ALL}",
'flags': f" {Fore.MAGENTA}{t_flags}{Style.RESET_ALL}" if flags else '',
'pre': ' ' if not compact else '',
'pre': ' ' if verbose else '',
}


def format_od_object(
node: Node, index: int, *, short=False, compact=False,
unused=False, verbose=False, raw=False,
node: Node, index: int, *, short=False,
unused=False, verbose: int=0, raw=False,
widths: dict[str, int]|None = None
) -> Generator[str, None, None]:
"""Return the print formatting for an object dictionary entry."""
Expand All@@ -211,7 +216,7 @@ def format_od_object(

# Get the header for the entry and output it unless it is empty
line, fields = format_od_header(
node, index, unused=unused, compact=compact, entry=param, raw=raw
node, index, unused=unused, verbose=verbose, entry=param, raw=raw
)
if not line:
return
Expand DownExpand Up@@ -292,7 +297,7 @@ def format_od_object(
t_comment = f"{Fore.LIGHTBLACK_EX}/* {t_comment} */{Style.RESET_ALL}"

# Omit printing the first element unless specifically requested
if (not verbose and i == 0
if (verbose < 2 and i == 0
and obj['struct'] & OD.MultipleSubindexes
and not t_comment
):
Expand DownExpand Up@@ -335,20 +340,20 @@ def format_od_object(
for infoentry in infos:
yield fmt.format(**infoentry)

if not compact and infos:
if verbose and infos:
yield ""


def format_diff_nodes(
od1: Node, od2: Node, *, data=False, raw=False,
od1: Node, od2: Node, *, data=False, raw=False, verbose: int=0,
internal=False, show=False
) -> Generator[str, None, None]:
""" Compare two object dictionaries and return the formatted differences. """

if internal or data:
diffs = jsonod.diff(od1, od2, internal=internal)
else:
diffs = text_diff(od1, od2, data_mode=raw)
diffs = text_diff(od1, od2, data_mode=raw, verbose=verbose)

rst = Style.RESET_ALL

Expand DownExpand Up@@ -413,7 +418,7 @@ def _pprint(text: str, prefix: str = ' '):
yield f"{Fore.RED}{chtype} {ppath} {change}{rst}"


def text_diff(od1: Node, od2: Node, data_mode: bool=False) -> TDiffNodes:
def text_diff(od1: Node, od2: Node, data_mode: bool=False, verbose: int=0) -> TDiffNodes:
""" Compare two object dictionaries as text and return the differences. """

# Get all indices for the nodes
Expand All@@ -433,15 +438,15 @@ def text_diff(od1: Node, od2: Node, data_mode: bool=False) -> TDiffNodes:
# Run through the formatting to get the width for the columns
widths: dict[str, int] = {}
if index in keys1:
list(format_od_object(od1, index, unused=True, widths=widths))
list(format_od_object(od1, index, unused=True, verbose=verbose, widths=widths))
if index in keys2:
list(format_od_object(od2, index, unused=True, widths=widths))
list(format_od_object(od2, index, unused=True, verbose=verbose, widths=widths))

if index in keys1:
text1 = list(format_od_object(od1, index, unused=True, widths=widths))
text1 = list(format_od_object(od1, index, unused=True, verbose=verbose, widths=widths))
entry1 = od1.GetIndexEntry(index)
if index in keys2:
text2 = list(format_od_object(od2, index, unused=True, widths=widths))
text2 = list(format_od_object(od2, index, unused=True, verbose=verbose, widths=widths))
entry2 = od2.GetIndexEntry(index)

if data_mode:
Expand Down
6 changes: 3 additions & 3 deletions tests/test_printing.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -18,7 +18,7 @@ def test_printing_format_node(odpath, file):
od.ID = 1

opts = FormatNodeOpts(
compact=False, short=False, unused=True, all=True, raw=False
verbose=True, short=False, unused=True, raw=False
)

lines = format_node(od, file, opts=opts)
Expand All@@ -27,7 +27,7 @@ def test_printing_format_node(odpath, file):
assert isinstance(line, str)

opts = FormatNodeOpts(
compact=False, short=False, unused=True, all=True, raw=False
verbose=True, short=False, unused=True, raw=False
)

lines = format_node(od, file, index=[0x1000], opts=opts)
Expand All@@ -36,7 +36,7 @@ def test_printing_format_node(odpath, file):
assert isinstance(line, str)

opts = FormatNodeOpts(
compact=False, short=False, unused=True, all=True, raw=False
verbose=True, short=False, unused=True, raw=False
)

with pytest.raises(ValueError) as exc:
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions src/objdictgen/__main__.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -149,6 +149,7 @@ def main(debugopts: DebugOpts, args: Sequence[str]|None = None):
""", aliases=['compare'])
subp.add_argument('od1', help="Object dictionary")
subp.add_argument('od2', help="Object dictionary")
subp.add_argument('-v', '--verbose', action="count", default=0, help="Verbose output (can be used multiple times)")
subp.add_argument('--show', action="store_true", help="Show difference data")
subp.add_argument('--internal', action="store_true", help="Diff internal object")
subp.add_argument('--data', action="store_true", help="Show difference as data")
Expand All@@ -166,9 +167,7 @@ def main(debugopts: DebugOpts, args: Sequence[str]|None = None):
""", aliases=['cat'])
subp.add_argument('od', nargs="+", help="Object dictionary")
subp.add_argument('-i', '--index', action="append", help="Specify parameter index to show")
subp.add_argument('--all', action="store_true",
help="Show all subindexes, including subindex 0")
subp.add_argument('--compact', action="store_true", help="Compact listing")
subp.add_argument('-v', '--verbose', action="count", default=0, help="Verbose output (can be used multiple times)")
subp.add_argument('--raw', action="store_true", help="Show raw parameter values")
subp.add_argument('--short', action="store_true", help="Do not list sub-index")
subp.add_argument('--unused', action="store_true", help="Include unused profile parameters")
Expand DownExpand Up@@ -276,7 +275,7 @@ def main(debugopts: DebugOpts, args: Sequence[str]|None = None):
od2 = open_od(opts.od2, validate=not opts.novalidate)

lines = list(format_diff_nodes(od1, od2, data=opts.data, raw=opts.raw,
internal=opts.internal, show=opts.show))
internal=opts.internal, show=opts.show, verbose=opts.verbose))

for line in lines:
print(line)
Expand Down
59 changes: 32 additions & 27 deletions src/objdictgen/printing.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -18,10 +18,9 @@
@dataclass
class FormatNodeOpts:
""" Options for formatting the node """
compact: bool = False
verbose: int = 0
short: bool = False
unused: bool = False
all: bool = False
raw: bool = False
internal: bool = False

Expand DownExpand Up@@ -78,25 +77,26 @@ def format_node(
extra = f"{pname} (not loaded)"
profiles.append(extra)

if not kwargs.get("compact"):
yield f"{Fore.CYAN}File:{Style.RESET_ALL} {name}"
yield f"{Fore.CYAN}Name:{Style.RESET_ALL} {node.Name} [{node.Type.upper()}] {node.Description}"
yield f"{Fore.CYAN}File:{Style.RESET_ALL} {name}"
yield f"{Fore.CYAN}Name:{Style.RESET_ALL} {node.Name} [{node.Type.upper()}] {node.Description}"
if opts.verbose:
tp = ", ".join(profiles) or None
yield f"{Fore.CYAN}Profiles:{Style.RESET_ALL} {tp}"
if node.ID:
yield f"{Fore.CYAN}ID:{Style.RESET_ALL} {node.ID}"
yield ""
if node.ID:
yield f"{Fore.CYAN}ID:{Style.RESET_ALL} {node.ID}"
yield ""

index_range = None
header = ''
last_is_equal = False

for k in keys:

# Get the index range title
ir = maps.INDEX_RANGES.get_index_range(k)
if index_range != ir:
index_range = ir
if not opts.compact:
if opts.verbose:
header = Fore.YELLOW + ir.description + Style.RESET_ALL

obj = node.GetIndexEntry(k)
Expand All@@ -107,14 +107,19 @@ def format_node(
if obj == minusobj:
linegen = format_od_object(node, k, short=True)
lines = [remove_color(line) for line in linegen]
lines[0] = Fore.LIGHTBLACK_EX + lines[0] + f" {Fore.LIGHTRED_EX}<EQUAL>{Style.RESET_ALL}"
pre = " " if opts.verbose else ''
lines[0] = f"{pre}{Fore.LIGHTBLACK_EX}{lines[0]} {Fore.GREEN}<EQUAL>{Style.RESET_ALL}"
yield from lines
last_is_equal = True
continue

if last_is_equal and opts.verbose:
yield ""

# Yield the text for the index
lines = list(format_od_object(
node, k, short=opts.short, compact=opts.compact, unused=opts.unused,
verbose=opts.all, raw=opts.raw
node, k, short=opts.short, verbose=opts.verbose, unused=opts.unused,
raw=opts.raw
))

if opts.internal and lines[-1] == "":
Expand All@@ -133,12 +138,12 @@ def format_node(
obj = node.GetIndexEntry(k)
lines = pformat(obj, width=TERM_COLS).splitlines()
yield from lines
if not opts.compact:
if opts.verbose:
yield ""


def format_od_header(
node: Node, index: int, *, unused=False, compact=False, raw=False,
node: Node, index: int, *, unused=False, verbose=False, raw=False,
entry: TIndexEntry|None = None
) -> tuple[str, dict[str, str]]:
"""Get the print output for a dictionary entry header"""
Expand DownExpand Up@@ -194,13 +199,13 @@ def format_od_header(
'name': f"{Fore.LIGHTWHITE_EX}{t_name}{Style.RESET_ALL}",
'struct': f"{Fore.LIGHTYELLOW_EX}[{t_string.upper()}]{Style.RESET_ALL}",
'flags': f" {Fore.MAGENTA}{t_flags}{Style.RESET_ALL}" if flags else '',
'pre': ' ' if not compact else '',
'pre': ' ' if verbose else '',
}


def format_od_object(
node: Node, index: int, *, short=False, compact=False,
unused=False, verbose=False, raw=False,
node: Node, index: int, *, short=False,
unused=False, verbose: int=0, raw=False,
widths: dict[str, int]|None = None
) -> Generator[str, None, None]:
"""Return the print formatting for an object dictionary entry."""
Expand All@@ -211,7 +216,7 @@ def format_od_object(

# Get the header for the entry and output it unless it is empty
line, fields = format_od_header(
node, index, unused=unused, compact=compact, entry=param, raw=raw
node, index, unused=unused, verbose=verbose, entry=param, raw=raw
)
if not line:
return
Expand DownExpand Up@@ -292,7 +297,7 @@ def format_od_object(
t_comment = f"{Fore.LIGHTBLACK_EX}/* {t_comment} */{Style.RESET_ALL}"

# Omit printing the first element unless specifically requested
if (not verbose and i == 0
if (verbose < 2 and i == 0
and obj['struct'] & OD.MultipleSubindexes
and not t_comment
):
Expand DownExpand Up@@ -335,20 +340,20 @@ def format_od_object(
for infoentry in infos:
yield fmt.format(**infoentry)

if not compact and infos:
if verbose and infos:
yield ""


def format_diff_nodes(
od1: Node, od2: Node, *, data=False, raw=False,
od1: Node, od2: Node, *, data=False, raw=False, verbose: int=0,
internal=False, show=False
) -> Generator[str, None, None]:
""" Compare two object dictionaries and return the formatted differences. """

if internal or data:
diffs = jsonod.diff(od1, od2, internal=internal)
else:
diffs = text_diff(od1, od2, data_mode=raw)
diffs = text_diff(od1, od2, data_mode=raw, verbose=verbose)

rst = Style.RESET_ALL

Expand DownExpand Up@@ -413,7 +418,7 @@ def _pprint(text: str, prefix: str = ' '):
yield f"{Fore.RED}{chtype} {ppath} {change}{rst}"


def text_diff(od1: Node, od2: Node, data_mode: bool=False) -> TDiffNodes:
def text_diff(od1: Node, od2: Node, data_mode: bool=False, verbose: int=0) -> TDiffNodes:
""" Compare two object dictionaries as text and return the differences. """

# Get all indices for the nodes
Expand All@@ -433,15 +438,15 @@ def text_diff(od1: Node, od2: Node, data_mode: bool=False) -> TDiffNodes:
# Run through the formatting to get the width for the columns
widths: dict[str, int] = {}
if index in keys1:
list(format_od_object(od1, index, unused=True, widths=widths))
list(format_od_object(od1, index, unused=True, verbose=verbose, widths=widths))
if index in keys2:
list(format_od_object(od2, index, unused=True, widths=widths))
list(format_od_object(od2, index, unused=True, verbose=verbose, widths=widths))

if index in keys1:
text1 = list(format_od_object(od1, index, unused=True, widths=widths))
text1 = list(format_od_object(od1, index, unused=True, verbose=verbose, widths=widths))
entry1 = od1.GetIndexEntry(index)
if index in keys2:
text2 = list(format_od_object(od2, index, unused=True, widths=widths))
text2 = list(format_od_object(od2, index, unused=True, verbose=verbose, widths=widths))
entry2 = od2.GetIndexEntry(index)

if data_mode:
Expand Down
6 changes: 3 additions & 3 deletions tests/test_printing.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -18,7 +18,7 @@ def test_printing_format_node(odpath, file):
od.ID = 1

opts = FormatNodeOpts(
compact=False, short=False, unused=True, all=True, raw=False
verbose=True, short=False, unused=True, raw=False
)

lines = format_node(od, file, opts=opts)
Expand All@@ -27,7 +27,7 @@ def test_printing_format_node(odpath, file):
assert isinstance(line, str)

opts = FormatNodeOpts(
compact=False, short=False, unused=True, all=True, raw=False
verbose=True, short=False, unused=True, raw=False
)

lines = format_node(od, file, index=[0x1000], opts=opts)
Expand All@@ -36,7 +36,7 @@ def test_printing_format_node(odpath, file):
assert isinstance(line, str)

opts = FormatNodeOpts(
compact=False, short=False, unused=True, all=True, raw=False
verbose=True, short=False, unused=True, raw=False
)

with pytest.raises(ValueError) as exc:
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions src/objdictgen/__main__.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -149,6 +149,7 @@ def main(debugopts: DebugOpts, args: Sequence[str]|None = None):
""", aliases=['compare'])
subp.add_argument('od1', help="Object dictionary")
subp.add_argument('od2', help="Object dictionary")
subp.add_argument('-v', '--verbose', action="count", default=0, help="Verbose output (can be used multiple times)")
subp.add_argument('--show', action="store_true", help="Show difference data")
subp.add_argument('--internal', action="store_true", help="Diff internal object")
subp.add_argument('--data', action="store_true", help="Show difference as data")
Expand All@@ -166,9 +167,7 @@ def main(debugopts: DebugOpts, args: Sequence[str]|None = None):
""", aliases=['cat'])
subp.add_argument('od', nargs="+", help="Object dictionary")
subp.add_argument('-i', '--index', action="append", help="Specify parameter index to show")
subp.add_argument('--all', action="store_true",
help="Show all subindexes, including subindex 0")
subp.add_argument('--compact', action="store_true", help="Compact listing")
subp.add_argument('-v', '--verbose', action="count", default=0, help="Verbose output (can be used multiple times)")
subp.add_argument('--raw', action="store_true", help="Show raw parameter values")
subp.add_argument('--short', action="store_true", help="Do not list sub-index")
subp.add_argument('--unused', action="store_true", help="Include unused profile parameters")
Expand DownExpand Up@@ -276,7 +275,7 @@ def main(debugopts: DebugOpts, args: Sequence[str]|None = None):
od2 = open_od(opts.od2, validate=not opts.novalidate)

lines = list(format_diff_nodes(od1, od2, data=opts.data, raw=opts.raw,
internal=opts.internal, show=opts.show))
internal=opts.internal, show=opts.show, verbose=opts.verbose))

for line in lines:
print(line)
Expand Down
59 changes: 32 additions & 27 deletions src/objdictgen/printing.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -18,10 +18,9 @@
@dataclass
class FormatNodeOpts:
""" Options for formatting the node """
compact: bool = False
verbose: int = 0
short: bool = False
unused: bool = False
all: bool = False
raw: bool = False
internal: bool = False

Expand DownExpand Up@@ -78,25 +77,26 @@ def format_node(
extra = f"{pname} (not loaded)"
profiles.append(extra)

if not kwargs.get("compact"):
yield f"{Fore.CYAN}File:{Style.RESET_ALL} {name}"
yield f"{Fore.CYAN}Name:{Style.RESET_ALL} {node.Name} [{node.Type.upper()}] {node.Description}"
yield f"{Fore.CYAN}File:{Style.RESET_ALL} {name}"
yield f"{Fore.CYAN}Name:{Style.RESET_ALL} {node.Name} [{node.Type.upper()}] {node.Description}"
if opts.verbose:
tp = ", ".join(profiles) or None
yield f"{Fore.CYAN}Profiles:{Style.RESET_ALL} {tp}"
if node.ID:
yield f"{Fore.CYAN}ID:{Style.RESET_ALL} {node.ID}"
yield ""
if node.ID:
yield f"{Fore.CYAN}ID:{Style.RESET_ALL} {node.ID}"
yield ""

index_range = None
header = ''
last_is_equal = False

for k in keys:

# Get the index range title
ir = maps.INDEX_RANGES.get_index_range(k)
if index_range != ir:
index_range = ir
if not opts.compact:
if opts.verbose:
header = Fore.YELLOW + ir.description + Style.RESET_ALL

obj = node.GetIndexEntry(k)
Expand All@@ -107,14 +107,19 @@ def format_node(
if obj == minusobj:
linegen = format_od_object(node, k, short=True)
lines = [remove_color(line) for line in linegen]
lines[0] = Fore.LIGHTBLACK_EX + lines[0] + f" {Fore.LIGHTRED_EX}<EQUAL>{Style.RESET_ALL}"
pre = " " if opts.verbose else ''
lines[0] = f"{pre}{Fore.LIGHTBLACK_EX}{lines[0]} {Fore.GREEN}<EQUAL>{Style.RESET_ALL}"
yield from lines
last_is_equal = True
continue

if last_is_equal and opts.verbose:
yield ""

# Yield the text for the index
lines = list(format_od_object(
node, k, short=opts.short, compact=opts.compact, unused=opts.unused,
verbose=opts.all, raw=opts.raw
node, k, short=opts.short, verbose=opts.verbose, unused=opts.unused,
raw=opts.raw
))

if opts.internal and lines[-1] == "":
Expand All@@ -133,12 +138,12 @@ def format_node(
obj = node.GetIndexEntry(k)
lines = pformat(obj, width=TERM_COLS).splitlines()
yield from lines
if not opts.compact:
if opts.verbose:
yield ""


def format_od_header(
node: Node, index: int, *, unused=False, compact=False, raw=False,
node: Node, index: int, *, unused=False, verbose=False, raw=False,
entry: TIndexEntry|None = None
) -> tuple[str, dict[str, str]]:
"""Get the print output for a dictionary entry header"""
Expand DownExpand Up@@ -194,13 +199,13 @@ def format_od_header(
'name': f"{Fore.LIGHTWHITE_EX}{t_name}{Style.RESET_ALL}",
'struct': f"{Fore.LIGHTYELLOW_EX}[{t_string.upper()}]{Style.RESET_ALL}",
'flags': f" {Fore.MAGENTA}{t_flags}{Style.RESET_ALL}" if flags else '',
'pre': ' ' if not compact else '',
'pre': ' ' if verbose else '',
}


def format_od_object(
node: Node, index: int, *, short=False, compact=False,
unused=False, verbose=False, raw=False,
node: Node, index: int, *, short=False,
unused=False, verbose: int=0, raw=False,
widths: dict[str, int]|None = None
) -> Generator[str, None, None]:
"""Return the print formatting for an object dictionary entry."""
Expand All@@ -211,7 +216,7 @@ def format_od_object(

# Get the header for the entry and output it unless it is empty
line, fields = format_od_header(
node, index, unused=unused, compact=compact, entry=param, raw=raw
node, index, unused=unused, verbose=verbose, entry=param, raw=raw
)
if not line:
return
Expand DownExpand Up@@ -292,7 +297,7 @@ def format_od_object(
t_comment = f"{Fore.LIGHTBLACK_EX}/* {t_comment} */{Style.RESET_ALL}"

# Omit printing the first element unless specifically requested
if (not verbose and i == 0
if (verbose < 2 and i == 0
and obj['struct'] & OD.MultipleSubindexes
and not t_comment
):
Expand DownExpand Up@@ -335,20 +340,20 @@ def format_od_object(
for infoentry in infos:
yield fmt.format(**infoentry)

if not compact and infos:
if verbose and infos:
yield ""


def format_diff_nodes(
od1: Node, od2: Node, *, data=False, raw=False,
od1: Node, od2: Node, *, data=False, raw=False, verbose: int=0,
internal=False, show=False
) -> Generator[str, None, None]:
""" Compare two object dictionaries and return the formatted differences. """

if internal or data:
diffs = jsonod.diff(od1, od2, internal=internal)
else:
diffs = text_diff(od1, od2, data_mode=raw)
diffs = text_diff(od1, od2, data_mode=raw, verbose=verbose)

rst = Style.RESET_ALL

Expand DownExpand Up@@ -413,7 +418,7 @@ def _pprint(text: str, prefix: str = ' '):
yield f"{Fore.RED}{chtype} {ppath} {change}{rst}"


def text_diff(od1: Node, od2: Node, data_mode: bool=False) -> TDiffNodes:
def text_diff(od1: Node, od2: Node, data_mode: bool=False, verbose: int=0) -> TDiffNodes:
""" Compare two object dictionaries as text and return the differences. """

# Get all indices for the nodes
Expand All@@ -433,15 +438,15 @@ def text_diff(od1: Node, od2: Node, data_mode: bool=False) -> TDiffNodes:
# Run through the formatting to get the width for the columns
widths: dict[str, int] = {}
if index in keys1:
list(format_od_object(od1, index, unused=True, widths=widths))
list(format_od_object(od1, index, unused=True, verbose=verbose, widths=widths))
if index in keys2:
list(format_od_object(od2, index, unused=True, widths=widths))
list(format_od_object(od2, index, unused=True, verbose=verbose, widths=widths))

if index in keys1:
text1 = list(format_od_object(od1, index, unused=True, widths=widths))
text1 = list(format_od_object(od1, index, unused=True, verbose=verbose, widths=widths))
entry1 = od1.GetIndexEntry(index)
if index in keys2:
text2 = list(format_od_object(od2, index, unused=True, widths=widths))
text2 = list(format_od_object(od2, index, unused=True, verbose=verbose, widths=widths))
entry2 = od2.GetIndexEntry(index)

if data_mode:
Expand Down
6 changes: 3 additions & 3 deletions tests/test_printing.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -18,7 +18,7 @@ def test_printing_format_node(odpath, file):
od.ID = 1

opts = FormatNodeOpts(
compact=False, short=False, unused=True, all=True, raw=False
verbose=True, short=False, unused=True, raw=False
)

lines = format_node(od, file, opts=opts)
Expand All@@ -27,7 +27,7 @@ def test_printing_format_node(odpath, file):
assert isinstance(line, str)

opts = FormatNodeOpts(
compact=False, short=False, unused=True, all=True, raw=False
verbose=True, short=False, unused=True, raw=False
)

lines = format_node(od, file, index=[0x1000], opts=opts)
Expand All@@ -36,7 +36,7 @@ def test_printing_format_node(odpath, file):
assert isinstance(line, str)

opts = FormatNodeOpts(
compact=False, short=False, unused=True, all=True, raw=False
verbose=True, short=False, unused=True, raw=False
)

with pytest.raises(ValueError) as exc:
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions src/objdictgen/__main__.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -149,6 +149,7 @@ def main(debugopts: DebugOpts, args: Sequence[str]|None = None):
""", aliases=['compare'])
subp.add_argument('od1', help="Object dictionary")
subp.add_argument('od2', help="Object dictionary")
subp.add_argument('-v', '--verbose', action="count", default=0, help="Verbose output (can be used multiple times)")
subp.add_argument('--show', action="store_true", help="Show difference data")
subp.add_argument('--internal', action="store_true", help="Diff internal object")
subp.add_argument('--data', action="store_true", help="Show difference as data")
Expand All@@ -166,9 +167,7 @@ def main(debugopts: DebugOpts, args: Sequence[str]|None = None):
""", aliases=['cat'])
subp.add_argument('od', nargs="+", help="Object dictionary")
subp.add_argument('-i', '--index', action="append", help="Specify parameter index to show")
subp.add_argument('--all', action="store_true",
help="Show all subindexes, including subindex 0")
subp.add_argument('--compact', action="store_true", help="Compact listing")
subp.add_argument('-v', '--verbose', action="count", default=0, help="Verbose output (can be used multiple times)")
subp.add_argument('--raw', action="store_true", help="Show raw parameter values")
subp.add_argument('--short', action="store_true", help="Do not list sub-index")
subp.add_argument('--unused', action="store_true", help="Include unused profile parameters")
Expand DownExpand Up@@ -276,7 +275,7 @@ def main(debugopts: DebugOpts, args: Sequence[str]|None = None):
od2 = open_od(opts.od2, validate=not opts.novalidate)

lines = list(format_diff_nodes(od1, od2, data=opts.data, raw=opts.raw,
internal=opts.internal, show=opts.show))
internal=opts.internal, show=opts.show, verbose=opts.verbose))

for line in lines:
print(line)
Expand Down
59 changes: 32 additions & 27 deletions src/objdictgen/printing.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -18,10 +18,9 @@
@dataclass
class FormatNodeOpts:
""" Options for formatting the node """
compact: bool = False
verbose: int = 0
short: bool = False
unused: bool = False
all: bool = False
raw: bool = False
internal: bool = False

Expand DownExpand Up@@ -78,25 +77,26 @@ def format_node(
extra = f"{pname} (not loaded)"
profiles.append(extra)

if not kwargs.get("compact"):
yield f"{Fore.CYAN}File:{Style.RESET_ALL} {name}"
yield f"{Fore.CYAN}Name:{Style.RESET_ALL} {node.Name} [{node.Type.upper()}] {node.Description}"
yield f"{Fore.CYAN}File:{Style.RESET_ALL} {name}"
yield f"{Fore.CYAN}Name:{Style.RESET_ALL} {node.Name} [{node.Type.upper()}] {node.Description}"
if opts.verbose:
tp = ", ".join(profiles) or None
yield f"{Fore.CYAN}Profiles:{Style.RESET_ALL} {tp}"
if node.ID:
yield f"{Fore.CYAN}ID:{Style.RESET_ALL} {node.ID}"
yield ""
if node.ID:
yield f"{Fore.CYAN}ID:{Style.RESET_ALL} {node.ID}"
yield ""

index_range = None
header = ''
last_is_equal = False

for k in keys:

# Get the index range title
ir = maps.INDEX_RANGES.get_index_range(k)
if index_range != ir:
index_range = ir
if not opts.compact:
if opts.verbose:
header = Fore.YELLOW + ir.description + Style.RESET_ALL

obj = node.GetIndexEntry(k)
Expand All@@ -107,14 +107,19 @@ def format_node(
if obj == minusobj:
linegen = format_od_object(node, k, short=True)
lines = [remove_color(line) for line in linegen]
lines[0] = Fore.LIGHTBLACK_EX + lines[0] + f" {Fore.LIGHTRED_EX}<EQUAL>{Style.RESET_ALL}"
pre = " " if opts.verbose else ''
lines[0] = f"{pre}{Fore.LIGHTBLACK_EX}{lines[0]} {Fore.GREEN}<EQUAL>{Style.RESET_ALL}"
yield from lines
last_is_equal = True
continue

if last_is_equal and opts.verbose:
yield ""

# Yield the text for the index
lines = list(format_od_object(
node, k, short=opts.short, compact=opts.compact, unused=opts.unused,
verbose=opts.all, raw=opts.raw
node, k, short=opts.short, verbose=opts.verbose, unused=opts.unused,
raw=opts.raw
))

if opts.internal and lines[-1] == "":
Expand All@@ -133,12 +138,12 @@ def format_node(
obj = node.GetIndexEntry(k)
lines = pformat(obj, width=TERM_COLS).splitlines()
yield from lines
if not opts.compact:
if opts.verbose:
yield ""


def format_od_header(
node: Node, index: int, *, unused=False, compact=False, raw=False,
node: Node, index: int, *, unused=False, verbose=False, raw=False,
entry: TIndexEntry|None = None
) -> tuple[str, dict[str, str]]:
"""Get the print output for a dictionary entry header"""
Expand DownExpand Up@@ -194,13 +199,13 @@ def format_od_header(
'name': f"{Fore.LIGHTWHITE_EX}{t_name}{Style.RESET_ALL}",
'struct': f"{Fore.LIGHTYELLOW_EX}[{t_string.upper()}]{Style.RESET_ALL}",
'flags': f" {Fore.MAGENTA}{t_flags}{Style.RESET_ALL}" if flags else '',
'pre': ' ' if not compact else '',
'pre': ' ' if verbose else '',
}


def format_od_object(
node: Node, index: int, *, short=False, compact=False,
unused=False, verbose=False, raw=False,
node: Node, index: int, *, short=False,
unused=False, verbose: int=0, raw=False,
widths: dict[str, int]|None = None
) -> Generator[str, None, None]:
"""Return the print formatting for an object dictionary entry."""
Expand All@@ -211,7 +216,7 @@ def format_od_object(

# Get the header for the entry and output it unless it is empty
line, fields = format_od_header(
node, index, unused=unused, compact=compact, entry=param, raw=raw
node, index, unused=unused, verbose=verbose, entry=param, raw=raw
)
if not line:
return
Expand DownExpand Up@@ -292,7 +297,7 @@ def format_od_object(
t_comment = f"{Fore.LIGHTBLACK_EX}/* {t_comment} */{Style.RESET_ALL}"

# Omit printing the first element unless specifically requested
if (not verbose and i == 0
if (verbose < 2 and i == 0
and obj['struct'] & OD.MultipleSubindexes
and not t_comment
):
Expand DownExpand Up@@ -335,20 +340,20 @@ def format_od_object(
for infoentry in infos:
yield fmt.format(**infoentry)

if not compact and infos:
if verbose and infos:
yield ""


def format_diff_nodes(
od1: Node, od2: Node, *, data=False, raw=False,
od1: Node, od2: Node, *, data=False, raw=False, verbose: int=0,
internal=False, show=False
) -> Generator[str, None, None]:
""" Compare two object dictionaries and return the formatted differences. """

if internal or data:
diffs = jsonod.diff(od1, od2, internal=internal)
else:
diffs = text_diff(od1, od2, data_mode=raw)
diffs = text_diff(od1, od2, data_mode=raw, verbose=verbose)

rst = Style.RESET_ALL

Expand DownExpand Up@@ -413,7 +418,7 @@ def _pprint(text: str, prefix: str = ' '):
yield f"{Fore.RED}{chtype} {ppath} {change}{rst}"


def text_diff(od1: Node, od2: Node, data_mode: bool=False) -> TDiffNodes:
def text_diff(od1: Node, od2: Node, data_mode: bool=False, verbose: int=0) -> TDiffNodes:
""" Compare two object dictionaries as text and return the differences. """

# Get all indices for the nodes
Expand All@@ -433,15 +438,15 @@ def text_diff(od1: Node, od2: Node, data_mode: bool=False) -> TDiffNodes:
# Run through the formatting to get the width for the columns
widths: dict[str, int] = {}
if index in keys1:
list(format_od_object(od1, index, unused=True, widths=widths))
list(format_od_object(od1, index, unused=True, verbose=verbose, widths=widths))
if index in keys2:
list(format_od_object(od2, index, unused=True, widths=widths))
list(format_od_object(od2, index, unused=True, verbose=verbose, widths=widths))

if index in keys1:
text1 = list(format_od_object(od1, index, unused=True, widths=widths))
text1 = list(format_od_object(od1, index, unused=True, verbose=verbose, widths=widths))
entry1 = od1.GetIndexEntry(index)
if index in keys2:
text2 = list(format_od_object(od2, index, unused=True, widths=widths))
text2 = list(format_od_object(od2, index, unused=True, verbose=verbose, widths=widths))
entry2 = od2.GetIndexEntry(index)

if data_mode:
Expand Down
6 changes: 3 additions & 3 deletions tests/test_printing.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -18,7 +18,7 @@ def test_printing_format_node(odpath, file):
od.ID = 1

opts = FormatNodeOpts(
compact=False, short=False, unused=True, all=True, raw=False
verbose=True, short=False, unused=True, raw=False
)

lines = format_node(od, file, opts=opts)
Expand All@@ -27,7 +27,7 @@ def test_printing_format_node(odpath, file):
assert isinstance(line, str)

opts = FormatNodeOpts(
compact=False, short=False, unused=True, all=True, raw=False
verbose=True, short=False, unused=True, raw=False
)

lines = format_node(od, file, index=[0x1000], opts=opts)
Expand All@@ -36,7 +36,7 @@ def test_printing_format_node(odpath, file):
assert isinstance(line, str)

opts = FormatNodeOpts(
compact=False, short=False, unused=True, all=True, raw=False
verbose=True, short=False, unused=True, raw=False
)

with pytest.raises(ValueError) as exc:
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions src/objdictgen/__main__.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -149,6 +149,7 @@ def main(debugopts: DebugOpts, args: Sequence[str]|None = None):
""", aliases=['compare'])
subp.add_argument('od1', help="Object dictionary")
subp.add_argument('od2', help="Object dictionary")
subp.add_argument('-v', '--verbose', action="count", default=0, help="Verbose output (can be used multiple times)")
subp.add_argument('--show', action="store_true", help="Show difference data")
subp.add_argument('--internal', action="store_true", help="Diff internal object")
subp.add_argument('--data', action="store_true", help="Show difference as data")
Expand All@@ -166,9 +167,7 @@ def main(debugopts: DebugOpts, args: Sequence[str]|None = None):
""", aliases=['cat'])
subp.add_argument('od', nargs="+", help="Object dictionary")
subp.add_argument('-i', '--index', action="append", help="Specify parameter index to show")
subp.add_argument('--all', action="store_true",
help="Show all subindexes, including subindex 0")
subp.add_argument('--compact', action="store_true", help="Compact listing")
subp.add_argument('-v', '--verbose', action="count", default=0, help="Verbose output (can be used multiple times)")
subp.add_argument('--raw', action="store_true", help="Show raw parameter values")
subp.add_argument('--short', action="store_true", help="Do not list sub-index")
subp.add_argument('--unused', action="store_true", help="Include unused profile parameters")
Expand DownExpand Up@@ -276,7 +275,7 @@ def main(debugopts: DebugOpts, args: Sequence[str]|None = None):
od2 = open_od(opts.od2, validate=not opts.novalidate)

lines = list(format_diff_nodes(od1, od2, data=opts.data, raw=opts.raw,
internal=opts.internal, show=opts.show))
internal=opts.internal, show=opts.show, verbose=opts.verbose))

for line in lines:
print(line)
Expand Down
59 changes: 32 additions & 27 deletions src/objdictgen/printing.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -18,10 +18,9 @@
@dataclass
class FormatNodeOpts:
""" Options for formatting the node """
compact: bool = False
verbose: int = 0
short: bool = False
unused: bool = False
all: bool = False
raw: bool = False
internal: bool = False

Expand DownExpand Up@@ -78,25 +77,26 @@ def format_node(
extra = f"{pname} (not loaded)"
profiles.append(extra)

if not kwargs.get("compact"):
yield f"{Fore.CYAN}File:{Style.RESET_ALL} {name}"
yield f"{Fore.CYAN}Name:{Style.RESET_ALL} {node.Name} [{node.Type.upper()}] {node.Description}"
yield f"{Fore.CYAN}File:{Style.RESET_ALL} {name}"
yield f"{Fore.CYAN}Name:{Style.RESET_ALL} {node.Name} [{node.Type.upper()}] {node.Description}"
if opts.verbose:
tp = ", ".join(profiles) or None
yield f"{Fore.CYAN}Profiles:{Style.RESET_ALL} {tp}"
if node.ID:
yield f"{Fore.CYAN}ID:{Style.RESET_ALL} {node.ID}"
yield ""
if node.ID:
yield f"{Fore.CYAN}ID:{Style.RESET_ALL} {node.ID}"
yield ""

index_range = None
header = ''
last_is_equal = False

for k in keys:

# Get the index range title
ir = maps.INDEX_RANGES.get_index_range(k)
if index_range != ir:
index_range = ir
if not opts.compact:
if opts.verbose:
header = Fore.YELLOW + ir.description + Style.RESET_ALL

obj = node.GetIndexEntry(k)
Expand All@@ -107,14 +107,19 @@ def format_node(
if obj == minusobj:
linegen = format_od_object(node, k, short=True)
lines = [remove_color(line) for line in linegen]
lines[0] = Fore.LIGHTBLACK_EX + lines[0] + f" {Fore.LIGHTRED_EX}<EQUAL>{Style.RESET_ALL}"
pre = " " if opts.verbose else ''
lines[0] = f"{pre}{Fore.LIGHTBLACK_EX}{lines[0]} {Fore.GREEN}<EQUAL>{Style.RESET_ALL}"
yield from lines
last_is_equal = True
continue

if last_is_equal and opts.verbose:
yield ""

# Yield the text for the index
lines = list(format_od_object(
node, k, short=opts.short, compact=opts.compact, unused=opts.unused,
verbose=opts.all, raw=opts.raw
node, k, short=opts.short, verbose=opts.verbose, unused=opts.unused,
raw=opts.raw
))

if opts.internal and lines[-1] == "":
Expand All@@ -133,12 +138,12 @@ def format_node(
obj = node.GetIndexEntry(k)
lines = pformat(obj, width=TERM_COLS).splitlines()
yield from lines
if not opts.compact:
if opts.verbose:
yield ""


def format_od_header(
node: Node, index: int, *, unused=False, compact=False, raw=False,
node: Node, index: int, *, unused=False, verbose=False, raw=False,
entry: TIndexEntry|None = None
) -> tuple[str, dict[str, str]]:
"""Get the print output for a dictionary entry header"""
Expand DownExpand Up@@ -194,13 +199,13 @@ def format_od_header(
'name': f"{Fore.LIGHTWHITE_EX}{t_name}{Style.RESET_ALL}",
'struct': f"{Fore.LIGHTYELLOW_EX}[{t_string.upper()}]{Style.RESET_ALL}",
'flags': f" {Fore.MAGENTA}{t_flags}{Style.RESET_ALL}" if flags else '',
'pre': ' ' if not compact else '',
'pre': ' ' if verbose else '',
}


def format_od_object(
node: Node, index: int, *, short=False, compact=False,
unused=False, verbose=False, raw=False,
node: Node, index: int, *, short=False,
unused=False, verbose: int=0, raw=False,
widths: dict[str, int]|None = None
) -> Generator[str, None, None]:
"""Return the print formatting for an object dictionary entry."""
Expand All@@ -211,7 +216,7 @@ def format_od_object(

# Get the header for the entry and output it unless it is empty
line, fields = format_od_header(
node, index, unused=unused, compact=compact, entry=param, raw=raw
node, index, unused=unused, verbose=verbose, entry=param, raw=raw
)
if not line:
return
Expand DownExpand Up@@ -292,7 +297,7 @@ def format_od_object(
t_comment = f"{Fore.LIGHTBLACK_EX}/* {t_comment} */{Style.RESET_ALL}"

# Omit printing the first element unless specifically requested
if (not verbose and i == 0
if (verbose < 2 and i == 0
and obj['struct'] & OD.MultipleSubindexes
and not t_comment
):
Expand DownExpand Up@@ -335,20 +340,20 @@ def format_od_object(
for infoentry in infos:
yield fmt.format(**infoentry)

if not compact and infos:
if verbose and infos:
yield ""


def format_diff_nodes(
od1: Node, od2: Node, *, data=False, raw=False,
od1: Node, od2: Node, *, data=False, raw=False, verbose: int=0,
internal=False, show=False
) -> Generator[str, None, None]:
""" Compare two object dictionaries and return the formatted differences. """

if internal or data:
diffs = jsonod.diff(od1, od2, internal=internal)
else:
diffs = text_diff(od1, od2, data_mode=raw)
diffs = text_diff(od1, od2, data_mode=raw, verbose=verbose)

rst = Style.RESET_ALL

Expand DownExpand Up@@ -413,7 +418,7 @@ def _pprint(text: str, prefix: str = ' '):
yield f"{Fore.RED}{chtype} {ppath} {change}{rst}"


def text_diff(od1: Node, od2: Node, data_mode: bool=False) -> TDiffNodes:
def text_diff(od1: Node, od2: Node, data_mode: bool=False, verbose: int=0) -> TDiffNodes:
""" Compare two object dictionaries as text and return the differences. """

# Get all indices for the nodes
Expand All@@ -433,15 +438,15 @@ def text_diff(od1: Node, od2: Node, data_mode: bool=False) -> TDiffNodes:
# Run through the formatting to get the width for the columns
widths: dict[str, int] = {}
if index in keys1:
list(format_od_object(od1, index, unused=True, widths=widths))
list(format_od_object(od1, index, unused=True, verbose=verbose, widths=widths))
if index in keys2:
list(format_od_object(od2, index, unused=True, widths=widths))
list(format_od_object(od2, index, unused=True, verbose=verbose, widths=widths))

if index in keys1:
text1 = list(format_od_object(od1, index, unused=True, widths=widths))
text1 = list(format_od_object(od1, index, unused=True, verbose=verbose, widths=widths))
entry1 = od1.GetIndexEntry(index)
if index in keys2:
text2 = list(format_od_object(od2, index, unused=True, widths=widths))
text2 = list(format_od_object(od2, index, unused=True, verbose=verbose, widths=widths))
entry2 = od2.GetIndexEntry(index)

if data_mode:
Expand Down
6 changes: 3 additions & 3 deletions tests/test_printing.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -18,7 +18,7 @@ def test_printing_format_node(odpath, file):
od.ID = 1

opts = FormatNodeOpts(
compact=False, short=False, unused=True, all=True, raw=False
verbose=True, short=False, unused=True, raw=False
)

lines = format_node(od, file, opts=opts)
Expand All@@ -27,7 +27,7 @@ def test_printing_format_node(odpath, file):
assert isinstance(line, str)

opts = FormatNodeOpts(
compact=False, short=False, unused=True, all=True, raw=False
verbose=True, short=False, unused=True, raw=False
)

lines = format_node(od, file, index=[0x1000], opts=opts)
Expand All@@ -36,7 +36,7 @@ def test_printing_format_node(odpath, file):
assert isinstance(line, str)

opts = FormatNodeOpts(
compact=False, short=False, unused=True, all=True, raw=False
verbose=True, short=False, unused=True, raw=False
)

with pytest.raises(ValueError) as exc:
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions src/objdictgen/__main__.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -149,6 +149,7 @@ def main(debugopts: DebugOpts, args: Sequence[str]|None = None):
""", aliases=['compare'])
subp.add_argument('od1', help="Object dictionary")
subp.add_argument('od2', help="Object dictionary")
subp.add_argument('-v', '--verbose', action="count", default=0, help="Verbose output (can be used multiple times)")
subp.add_argument('--show', action="store_true", help="Show difference data")
subp.add_argument('--internal', action="store_true", help="Diff internal object")
subp.add_argument('--data', action="store_true", help="Show difference as data")
Expand All@@ -166,9 +167,7 @@ def main(debugopts: DebugOpts, args: Sequence[str]|None = None):
""", aliases=['cat'])
subp.add_argument('od', nargs="+", help="Object dictionary")
subp.add_argument('-i', '--index', action="append", help="Specify parameter index to show")
subp.add_argument('--all', action="store_true",
help="Show all subindexes, including subindex 0")
subp.add_argument('--compact', action="store_true", help="Compact listing")
subp.add_argument('-v', '--verbose', action="count", default=0, help="Verbose output (can be used multiple times)")
subp.add_argument('--raw', action="store_true", help="Show raw parameter values")
subp.add_argument('--short', action="store_true", help="Do not list sub-index")
subp.add_argument('--unused', action="store_true", help="Include unused profile parameters")
Expand DownExpand Up@@ -276,7 +275,7 @@ def main(debugopts: DebugOpts, args: Sequence[str]|None = None):
od2 = open_od(opts.od2, validate=not opts.novalidate)

lines = list(format_diff_nodes(od1, od2, data=opts.data, raw=opts.raw,
internal=opts.internal, show=opts.show))
internal=opts.internal, show=opts.show, verbose=opts.verbose))

for line in lines:
print(line)
Expand Down
59 changes: 32 additions & 27 deletions src/objdictgen/printing.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -18,10 +18,9 @@
@dataclass
class FormatNodeOpts:
""" Options for formatting the node """
compact: bool = False
verbose: int = 0
short: bool = False
unused: bool = False
all: bool = False
raw: bool = False
internal: bool = False

Expand DownExpand Up@@ -78,25 +77,26 @@ def format_node(
extra = f"{pname} (not loaded)"
profiles.append(extra)

if not kwargs.get("compact"):
yield f"{Fore.CYAN}File:{Style.RESET_ALL} {name}"
yield f"{Fore.CYAN}Name:{Style.RESET_ALL} {node.Name} [{node.Type.upper()}] {node.Description}"
yield f"{Fore.CYAN}File:{Style.RESET_ALL} {name}"
yield f"{Fore.CYAN}Name:{Style.RESET_ALL} {node.Name} [{node.Type.upper()}] {node.Description}"
if opts.verbose:
tp = ", ".join(profiles) or None
yield f"{Fore.CYAN}Profiles:{Style.RESET_ALL} {tp}"
if node.ID:
yield f"{Fore.CYAN}ID:{Style.RESET_ALL} {node.ID}"
yield ""
if node.ID:
yield f"{Fore.CYAN}ID:{Style.RESET_ALL} {node.ID}"
yield ""

index_range = None
header = ''
last_is_equal = False

for k in keys:

# Get the index range title
ir = maps.INDEX_RANGES.get_index_range(k)
if index_range != ir:
index_range = ir
if not opts.compact:
if opts.verbose:
header = Fore.YELLOW + ir.description + Style.RESET_ALL

obj = node.GetIndexEntry(k)
Expand All@@ -107,14 +107,19 @@ def format_node(
if obj == minusobj:
linegen = format_od_object(node, k, short=True)
lines = [remove_color(line) for line in linegen]
lines[0] = Fore.LIGHTBLACK_EX + lines[0] + f" {Fore.LIGHTRED_EX}<EQUAL>{Style.RESET_ALL}"
pre = " " if opts.verbose else ''
lines[0] = f"{pre}{Fore.LIGHTBLACK_EX}{lines[0]} {Fore.GREEN}<EQUAL>{Style.RESET_ALL}"
yield from lines
last_is_equal = True
continue

if last_is_equal and opts.verbose:
yield ""

# Yield the text for the index
lines = list(format_od_object(
node, k, short=opts.short, compact=opts.compact, unused=opts.unused,
verbose=opts.all, raw=opts.raw
node, k, short=opts.short, verbose=opts.verbose, unused=opts.unused,
raw=opts.raw
))

if opts.internal and lines[-1] == "":
Expand All@@ -133,12 +138,12 @@ def format_node(
obj = node.GetIndexEntry(k)
lines = pformat(obj, width=TERM_COLS).splitlines()
yield from lines
if not opts.compact:
if opts.verbose:
yield ""


def format_od_header(
node: Node, index: int, *, unused=False, compact=False, raw=False,
node: Node, index: int, *, unused=False, verbose=False, raw=False,
entry: TIndexEntry|None = None
) -> tuple[str, dict[str, str]]:
"""Get the print output for a dictionary entry header"""
Expand DownExpand Up@@ -194,13 +199,13 @@ def format_od_header(
'name': f"{Fore.LIGHTWHITE_EX}{t_name}{Style.RESET_ALL}",
'struct': f"{Fore.LIGHTYELLOW_EX}[{t_string.upper()}]{Style.RESET_ALL}",
'flags': f" {Fore.MAGENTA}{t_flags}{Style.RESET_ALL}" if flags else '',
'pre': ' ' if not compact else '',
'pre': ' ' if verbose else '',
}


def format_od_object(
node: Node, index: int, *, short=False, compact=False,
unused=False, verbose=False, raw=False,
node: Node, index: int, *, short=False,
unused=False, verbose: int=0, raw=False,
widths: dict[str, int]|None = None
) -> Generator[str, None, None]:
"""Return the print formatting for an object dictionary entry."""
Expand All@@ -211,7 +216,7 @@ def format_od_object(

# Get the header for the entry and output it unless it is empty
line, fields = format_od_header(
node, index, unused=unused, compact=compact, entry=param, raw=raw
node, index, unused=unused, verbose=verbose, entry=param, raw=raw
)
if not line:
return
Expand DownExpand Up@@ -292,7 +297,7 @@ def format_od_object(
t_comment = f"{Fore.LIGHTBLACK_EX}/* {t_comment} */{Style.RESET_ALL}"

# Omit printing the first element unless specifically requested
if (not verbose and i == 0
if (verbose < 2 and i == 0
and obj['struct'] & OD.MultipleSubindexes
and not t_comment
):
Expand DownExpand Up@@ -335,20 +340,20 @@ def format_od_object(
for infoentry in infos:
yield fmt.format(**infoentry)

if not compact and infos:
if verbose and infos:
yield ""


def format_diff_nodes(
od1: Node, od2: Node, *, data=False, raw=False,
od1: Node, od2: Node, *, data=False, raw=False, verbose: int=0,
internal=False, show=False
) -> Generator[str, None, None]:
""" Compare two object dictionaries and return the formatted differences. """

if internal or data:
diffs = jsonod.diff(od1, od2, internal=internal)
else:
diffs = text_diff(od1, od2, data_mode=raw)
diffs = text_diff(od1, od2, data_mode=raw, verbose=verbose)

rst = Style.RESET_ALL

Expand DownExpand Up@@ -413,7 +418,7 @@ def _pprint(text: str, prefix: str = ' '):
yield f"{Fore.RED}{chtype} {ppath} {change}{rst}"


def text_diff(od1: Node, od2: Node, data_mode: bool=False) -> TDiffNodes:
def text_diff(od1: Node, od2: Node, data_mode: bool=False, verbose: int=0) -> TDiffNodes:
""" Compare two object dictionaries as text and return the differences. """

# Get all indices for the nodes
Expand All@@ -433,15 +438,15 @@ def text_diff(od1: Node, od2: Node, data_mode: bool=False) -> TDiffNodes:
# Run through the formatting to get the width for the columns
widths: dict[str, int] = {}
if index in keys1:
list(format_od_object(od1, index, unused=True, widths=widths))
list(format_od_object(od1, index, unused=True, verbose=verbose, widths=widths))
if index in keys2:
list(format_od_object(od2, index, unused=True, widths=widths))
list(format_od_object(od2, index, unused=True, verbose=verbose, widths=widths))

if index in keys1:
text1 = list(format_od_object(od1, index, unused=True, widths=widths))
text1 = list(format_od_object(od1, index, unused=True, verbose=verbose, widths=widths))
entry1 = od1.GetIndexEntry(index)
if index in keys2:
text2 = list(format_od_object(od2, index, unused=True, widths=widths))
text2 = list(format_od_object(od2, index, unused=True, verbose=verbose, widths=widths))
entry2 = od2.GetIndexEntry(index)

if data_mode:
Expand Down
6 changes: 3 additions & 3 deletions tests/test_printing.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -18,7 +18,7 @@ def test_printing_format_node(odpath, file):
od.ID = 1

opts = FormatNodeOpts(
compact=False, short=False, unused=True, all=True, raw=False
verbose=True, short=False, unused=True, raw=False
)

lines = format_node(od, file, opts=opts)
Expand All@@ -27,7 +27,7 @@ def test_printing_format_node(odpath, file):
assert isinstance(line, str)

opts = FormatNodeOpts(
compact=False, short=False, unused=True, all=True, raw=False
verbose=True, short=False, unused=True, raw=False
)

lines = format_node(od, file, index=[0x1000], opts=opts)
Expand All@@ -36,7 +36,7 @@ def test_printing_format_node(odpath, file):
assert isinstance(line, str)

opts = FormatNodeOpts(
compact=False, short=False, unused=True, all=True, raw=False
verbose=True, short=False, unused=True, raw=False
)

with pytest.raises(ValueError) as exc:
Expand Down
Loading