mirror of
https://github.com/volatilityfoundation/volatility3.git
synced 2026-09-07 18:27:39 +02:00
Add in initial renderer code for CLI table formatting.
This commit is contained in:
@@ -20,6 +20,8 @@
|
||||
|
||||
import datetime
|
||||
import logging
|
||||
import random
|
||||
import string
|
||||
import sys
|
||||
from typing import Callable, Any
|
||||
|
||||
@@ -115,9 +117,6 @@ class QuickTextRenderer(interfaces.renderers.Renderer):
|
||||
'default': Optional(lambda x: "{}".format(x))
|
||||
}
|
||||
|
||||
def __init__(self, options = None) -> None:
|
||||
super().__init__(options)
|
||||
|
||||
def get_render_options(self):
|
||||
pass
|
||||
|
||||
@@ -155,3 +154,60 @@ class QuickTextRenderer(interfaces.renderers.Renderer):
|
||||
grid.populate(visitor, outfd)
|
||||
|
||||
outfd.write("\n")
|
||||
|
||||
|
||||
class PrettyTextRenderer(interfaces.renderers.Renderer):
|
||||
type_renderers = QuickTextRenderer.type_renderers
|
||||
|
||||
def get_render_options(self):
|
||||
pass
|
||||
|
||||
def render(self, grid: interfaces.renderers.TreeGrid) -> None:
|
||||
"""
|
||||
Renders each column immediately to stdout.
|
||||
|
||||
This does not format each line's width appropriately, it merely tab separates each field
|
||||
|
||||
Args:
|
||||
grid: The TreeGrid object to render
|
||||
|
||||
"""
|
||||
# TODO: Docstrings
|
||||
# TODO: Improve text output
|
||||
outfd = sys.stdout
|
||||
|
||||
outfd.write("Formatting...\r")
|
||||
|
||||
display_alignment = ">"
|
||||
column_separator = " | "
|
||||
|
||||
tree_indent_column = ''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(20))
|
||||
max_column_widths = dict([(column, len(column.name)) for column in grid.columns])
|
||||
|
||||
def visitor(node, accumulator):
|
||||
# Nodes always have a path value, giving them a path_depth of at least 1, we use max just in case
|
||||
max_column_widths[tree_indent_column] = max(max_column_widths.get(tree_indent_column, 0), node.path_depth)
|
||||
line = {}
|
||||
for column in grid.columns:
|
||||
renderer = self.type_renderers.get(column.type, self.type_renderers['default'])
|
||||
data = renderer(node.values[column.index])
|
||||
max_column_widths[column] = max(max_column_widths.get(column, 0), len(data))
|
||||
line[column] = data
|
||||
accumulator.append((node.path_depth, line))
|
||||
return accumulator
|
||||
|
||||
final_output = []
|
||||
grid.populate(visitor, final_output)
|
||||
|
||||
# Always align the tree to the left
|
||||
format_string = ["{0:<" + str(max_column_widths[tree_indent_column]) + "s}"]
|
||||
for column in grid.columns:
|
||||
format_string.append("{" + str(column.index + 1) + ":" + display_alignment +
|
||||
str(max_column_widths[column]) + "s}")
|
||||
|
||||
format_string = column_separator.join(format_string) + "\n"
|
||||
|
||||
column_titles = [""] + [column.name for column in grid.columns]
|
||||
outfd.write(format_string.format(*column_titles))
|
||||
for (depth, line) in final_output:
|
||||
outfd.write(format_string.format("*" * depth, *[line[x] for x in line]))
|
||||
|
||||
@@ -34,7 +34,7 @@ RenderOption = Any
|
||||
class Renderer(metaclass = ABCMeta):
|
||||
"""Class that defines the interface that all output renderers must support"""
|
||||
|
||||
def __init__(self, options: List[RenderOption]) -> None:
|
||||
def __init__(self, options: Optional[List[RenderOption]] = None) -> None:
|
||||
"""Accepts an options object to configure the renderers"""
|
||||
# FIXME: Once the config option objects are in place, put the _type_check in place
|
||||
|
||||
|
||||
Reference in New Issue
Block a user