Skip to content

Commit

Permalink
refactor(ui): rearrange widgets
Browse files Browse the repository at this point in the history
The widgets have been rearranged to make better use of the available
space and make the TUI look more tidy. Some widgets have also been
added in the process, like the Python version and the current
threshold value.

Table widgets now also support scrolling all the way to the top and
the bottom.

Profile mode also has color coding.
  • Loading branch information
P403n1x87 committed Nov 6, 2021
1 parent ecea40b commit d1d0987
Show file tree
Hide file tree
Showing 8 changed files with 117 additions and 87 deletions.
9 changes: 2 additions & 7 deletions austin_tui/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,13 +99,8 @@ def on_ready(
self._controller.start()

self._view.set_mode(self._meta["mode"])

self._view.pid_label.set_text("PPID" if self._args.children else "PID")
self._view.pid.set_text(child_process.pid)

self._view.thread_name_label.set_text(
"{}TID".format("PID:" if self._args.children else "")
)
self._view.set_pid(child_process.pid, self._args.children)
self._view.set_python(self.python_version)

def on_terminate(self, stats: str) -> None:
"""Austin terminate callback."""
Expand Down
32 changes: 13 additions & 19 deletions austin_tui/adapters.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,18 +134,6 @@ def update(self, data: int) -> bool:
return self._view.samples.set_text(data)


class ThreadTotalAdapter(FreezableAdapter):
"""Total number of threads adapter."""

def transform(self) -> int:
"""Retrieve the number."""
return len(self._model.austin.threads)

def update(self, data: int) -> bool:
"""Update the widget."""
return self._view.thread_total.set_text(data)


class CpuAdapter(Adapter):
"""CPU metrics adapter."""

Expand Down Expand Up @@ -199,28 +187,34 @@ def update(self, data: str) -> bool:
class CurrentThreadAdapter(Adapter):
"""Currently selected thread adapter."""

def transform(self) -> str:
def transform(self) -> Union[str, AttrString]:
"""Get current thread."""
austin = self._model.frozen_austin if self._model.frozen else self._model.austin
return str(austin.current_thread + 1) if austin.threads else "--"
n = len(austin.threads)
if not n:
return "--/--"

def update(self, data: str) -> bool:
return self._view.markup(
f"<thread>{austin.current_thread + 1}</thread><hdrbox>/{n}</hdrbox>"
)

def update(self, data: Union[str, AttrString]) -> bool:
"""Update the widget."""
return self._view.thread_num.set_text(data)


class ThreadNameAdapter(FreezableAdapter):
"""Currently selected thread name adapter."""

def transform(self) -> str:
def transform(self) -> Union[str, AttrString]:
"""Get the thread name."""
austin = self._model.frozen_austin if self._model.frozen else self._model.austin
if austin.threads:
pid, _, thread_id = austin.threads[austin.current_thread].partition(":")
return (f"{pid}:" if int(pid) else "") + thread_id
pid, _, tid = austin.threads[austin.current_thread].partition(":")
return self._view.markup(f"<pid><b>{pid}</b></pid>:<tid><b>{tid}</b></tid>")
return "--:--"

def update(self, data: str) -> bool:
def update(self, data: Union[str, AttrString]) -> bool:
"""Update the widget."""
return self._view.thread_name.set_text(data)

Expand Down
9 changes: 2 additions & 7 deletions austin_tui/controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@
from austin_tui.adapters import ThreadDataAdapter
from austin_tui.adapters import ThreadFullDataAdapter
from austin_tui.adapters import ThreadNameAdapter
from austin_tui.adapters import ThreadTotalAdapter
from austin_tui.model import Model
from austin_tui.view import ViewBuilder

Expand All @@ -61,7 +60,6 @@ class AustinTUIController:
memory = MemoryAdapter
duration = DurationAdapter
samples = CountAdapter
threads = ThreadTotalAdapter
current_thread = CurrentThreadAdapter
thread_name = ThreadNameAdapter
thread_data = ThreadDataAdapter
Expand Down Expand Up @@ -146,9 +144,6 @@ def update(self) -> bool:
# Samples count
self.samples()

# Count total threads (across processes)
self.threads()

if self.model.austin.stats.timestamp > self._last_timestamp:
return self.set_thread()

Expand Down Expand Up @@ -266,11 +261,11 @@ def _change_threshold(self, delta: float) -> float:
async def on_threshold_up(self, _: Any = None) -> bool:
"""Handle threshold up."""
th = self._change_threshold(0.01) * 100.0
self.view.notification.set_text(f"Threshold increased to {th:.0f}%")
self.view.threshold.set_text(f"{th:.0f}%")
return True

async def on_threshold_down(self, _: Any = None) -> bool:
"""Handle threshold down."""
th = self._change_threshold(-0.01) * 100.0
self.view.notification.set_text(f"Threshold decreased to {th:.0f}%")
self.view.threshold.set_text(f"{th:.0f}%")
return True
2 changes: 2 additions & 0 deletions austin_tui/model/austin.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,8 @@ def update(self, raw_sample: str) -> None:
if self.mode is AustinProfileMode.MEMORY
else MetricType.TIME,
)
if sample.metric.value < 0:
return
self._stats.update(sample)
self._stats.timestamp = time()
thread_key = f"{sample.pid}:{sample.thread}"
Expand Down
26 changes: 23 additions & 3 deletions austin_tui/view/austin.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,16 @@ async def on_table_pgdown(self, data: Any = None) -> bool:
self.stats_view.refresh()
return False

async def on_table_home(self, _: Any = None) -> bool:
self.stats_view.top()
self.stats_view.refresh()
return False

async def on_table_end(self, _: Any = None) -> bool:
self.stats_view.bottom()
self.stats_view.refresh()
return False

async def on_play_pause(self, _: Any = None) -> bool:
"""Play/pause handler."""
if self._stopped:
Expand Down Expand Up @@ -134,8 +144,8 @@ def stop(self) -> None:

self._stopped = True
self.logo.set_color("stopped")
self.cpu.set_text("--%")
self.mem.set_text("--M")
self.cpu.set_text("--% ")
self.mem.set_text("--M ")
self.play_pause_cmd.set_color("disabled")

self.table.draw()
Expand Down Expand Up @@ -186,10 +196,20 @@ def scale_time(
def set_mode(self, mode: str) -> None:
"""Set profiling mode."""
self.profile_mode.set_text(
{
" "
+ {
"wall": "Wall Time Profile",
"cpu": "CPU Time Profile",
"memory": "Memory Profile",
}[mode]
)
self.profile_mode.set_color(f"mode_{mode}")

def set_pid(self, pid: int, children: bool) -> None:
"""Set the PID."""
self.pid_label.set_text("PPID" if children else "PID")
self.pid.set_text(self.markup(f"<pid><b>{pid}</b></pid>"))

def set_python(self, version: str) -> None:
"""Set the Python version"""
self.python.set_text(".".join([str(_) for _ in version]))
117 changes: 66 additions & 51 deletions austin_tui/view/tui.austinui
Original file line number Diff line number Diff line change
Expand Up @@ -44,71 +44,77 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. -->
</aui:Box>

<aui:Box name="inner_info_box" flow="vertical">
<aui:Label name="profile_mode"
text="Time Mode"
bold="true" />
<aui:Box name="inner_info_box_header" flow="horizontal">
<aui:Label name="profile_mode"
text="Unknown Mode"
bold="true" />

<aui:Box name="inner_info_box_1" flow="horizontal">
<aui:Label name="pid_label" text="PID" width="6" />
<aui:Label name="pid"
<aui:Label name="cpu_label" align="right" text="CPU" width="4" color="hdrbox" />
<aui:Label name="cpu"
align="right"
width="6"
color="hdrbox"
width="6" />
<aui:BarPlot name="cpu_plot"
scale="100"
init="0"
color="cpu" />

<aui:Label name="mem_label" align="right" text="MEM" width="6" color="hdrbox" />
<aui:Label name="mem"
align="right"
color="hdrbox"
width="6" />
<aui:BarPlot name="mem_plot"
scale="100"
init="0"
color="mem" />

<aui:Label name="thread_num"
align="center"
width="11"
text="1"
color="hdrbox"
bold="true" />
</aui:Box>

<aui:Label name="cmd_line_label" text="CMD " align="right" width="6" />
<aui:Box name="inner_info_box_1" flow="horizontal">
<aui:Label name="cmd_line_label" text="Command" width="8" />
<aui:Label name="cmd_line"
bold="true" />
</aui:Box>

<aui:Box name="inner_info_box_2" flow="horizontal">
<aui:Label name="thread_name_label" text="TID" width="8" />
<aui:Label name="thread_name"
width="20"
<aui:Label name="python_label" text="Python" width="7" />
<aui:Label name="python"
width="10"
bold="true" />

<aui:Label name="thread_num"
align="center"
width="5"
text="1"
color="thread"
<aui:Label name="pid_label" text="PID" width="4" />
<aui:Label name="pid"
width="12"
bold="true" />
<aui:Label name="of" align="center" width="4" text="of" bold="true" />
<aui:Label name="thread_total"
align="center"
width="5"
text="2" />

<aui:Label name="cpu_label" align="right" text="CPU" width="5" />
<aui:Label name="cpu"
align="right"
width="6" />
<aui:BarPlot name="cpu_plot"
scale="100"
init="0"
color="cpu" />
<aui:Label name="thread_name_label" text="PID:TID" width="8" />
<aui:Label name="thread_name"
width="20"
bold="true" />
</aui:Box>

<aui:Box name="inner_info_box_3" flow="horizontal">
<aui:Label name="samples_label" text="Samples" width="8" />
<aui:Label name="samples"
align="right"
width="10"
width="9"
bold="true" />

<aui:Label name="duration_label" align="right" text="Duration" width="10" />
<aui:Label name="duration_label" text="⏲️" width="4" />
<aui:Label name="duration"
align="right"
width="10"
width="12"
bold="true" />

<aui:Label name="mem_label" align="right" text="MEM" width="9" />
<aui:Label name="mem"
align="right"
width="6" />
<aui:BarPlot name="mem_plot"
scale="100"
init="0"
color="mem" />
<aui:Label name="threshold_label" text="Threshold" width="10" />
<aui:Label name="threshold"
width="5"
text="0%"
bold="true" />
</aui:Box>
</aui:Box>
</aui:Box>
Expand Down Expand Up @@ -187,8 +193,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. -->
off="cmd_off"
state="0" />
<aui:Label name="full_mode_label"
text="Full Mode"
width="11"
text="Full"
width="6"
align="center" />

<aui:Label name="save_cmd"
Expand Down Expand Up @@ -246,25 +252,31 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. -->

<aui:signal key="KEY_PPAGE" handler="on_table_pgup" />
<aui:signal key="KEY_NPAGE" handler="on_table_pgdown" />
<aui:signal key="KEY_HOME" handler="on_table_home" />
<aui:signal key="KEY_END" handler="on_table_end" />

<aui:signal key="+" handler="on_threshold_up" />
<aui:signal key="-" handler="on_threshold_down" />

<!-- Palette -->
<!-- See https://github.com/gookit/color/blob/c7dc09464b28518c2ae383fa16b989e7c0169599/_examples/images/color-256.png -->

<aui:palette>
<aui:color name="stopped" fg="1" />
<aui:color name="paused" fg="3" />
<aui:color name="running" fg="10" />
<aui:color name="disabled" bg="242" />

<aui:color name="mode_cpu" fg="206" />
<aui:color name="mode_wall" fg="227" />
<aui:color name="mode_memory" fg="46" />
<aui:color name="mode_cpu" bg="197" fg="254" />
<aui:color name="mode_wall" bg="227" fg="238" />
<aui:color name="mode_memory" bg="46" fg="238" />

<aui:color name="cpu" fg="4" />
<aui:color name="mem" fg="2" />
<aui:color name="thread" fg="11" />
<aui:color name="hdrbox" bg="236" />

<aui:color name="cpu" fg="4" bg="238" />
<aui:color name="mem" fg="2" bg="238" />

<aui:color name="thread" fg="11" bg="236" />
<aui:color name="inactive" fg="242" />
<aui:color name="notify" fg="246" />

Expand All @@ -287,5 +299,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. -->
<aui:color name="lineno" fg="30" />

<aui:color name="exec" fg="2" />

<aui:color name="pid" fg="229" />
<aui:color name="tid" fg="159" />
</aui:palette>
</aui:AustinView>
1 change: 1 addition & 0 deletions austin_tui/widgets/label.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ def draw(self) -> bool:
return False

if isinstance(self.text, AttrString):
win.addstr(self.y, self.x, " " * width, self.attr)
x = self.x
if self.align == TextAlign.RIGHT and len(self.text) < width:
x += width - len(self.text)
Expand Down
8 changes: 8 additions & 0 deletions austin_tui/widgets/scroll.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,14 @@ def scroll_up(self, lines: int = 1) -> None:

self._draw_scroll_bar()

def top(self) -> None:
self.curr_y = 0
self._draw_scroll_bar()

def bottom(self) -> None:
self.curr_y = self.h - self.height
self._draw_scroll_bar()

def get_view_size(self) -> Tuple[int, int]:
"""Get the scroll view size.
Expand Down

0 comments on commit d1d0987

Please sign in to comment.