llvm/lldb/utils/lui/breakwin.py

##===-- breakwin.py ------------------------------------------*- Python -*-===##
##
# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
# See https://llvm.org/LICENSE.txt for license information.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
##
##===----------------------------------------------------------------------===##

import cui
import curses
import lldb
import lldbutil
import re


class BreakWin(cui.ListWin):
    def __init__(self, driver, x, y, w, h):
        super(BreakWin, self).__init__(x, y, w, h)
        self.driver = driver
        self.update()
        self.showDetails = {}

    def handleEvent(self, event):
        if isinstance(event, lldb.SBEvent):
            if lldb.SBBreakpoint.EventIsBreakpointEvent(event):
                self.update()
        if isinstance(event, int):
            if event == ord("d"):
                self.deleteSelected()
            if event == curses.ascii.NL or event == curses.ascii.SP:
                self.toggleSelected()
            elif event == curses.ascii.TAB:
                if self.getSelected() != -1:
                    target = self.driver.getTarget()
                    if not target.IsValid():
                        return
                    i = target.GetBreakpointAtIndex(self.getSelected()).id
                    self.showDetails[i] = not self.showDetails[i]
                    self.update()
        super(BreakWin, self).handleEvent(event)

    def toggleSelected(self):
        if self.getSelected() == -1:
            return
        target = self.driver.getTarget()
        if not target.IsValid():
            return
        bp = target.GetBreakpointAtIndex(self.getSelected())
        bp.SetEnabled(not bp.IsEnabled())

    def deleteSelected(self):
        if self.getSelected() == -1:
            return
        target = self.driver.getTarget()
        if not target.IsValid():
            return
        bp = target.GetBreakpointAtIndex(self.getSelected())
        target.BreakpointDelete(bp.id)

    def update(self):
        target = self.driver.getTarget()
        if not target.IsValid():
            self.win.erase()
            self.win.noutrefresh()
            return
        selected = self.getSelected()
        self.clearItems()
        for i in range(0, target.GetNumBreakpoints()):
            bp = target.GetBreakpointAtIndex(i)
            if bp.IsInternal():
                continue
            text = lldbutil.get_description(bp)
            # FIXME: Use an API for this, not parsing the description.
            match = re.search("SBBreakpoint: id = ([^,]+), (.*)", text)
            try:
                id = match.group(1)
                desc = match.group(2).strip()
                if bp.IsEnabled():
                    text = "%s: %s" % (id, desc)
                else:
                    text = "%s: (disabled) %s" % (id, desc)
            except ValueError as e:
                # bp unparsable
                pass

            if self.showDetails.setdefault(bp.id, False):
                for location in bp:
                    desc = lldbutil.get_description(
                        location, lldb.eDescriptionLevelFull
                    )
                    text += "\n  " + desc
            self.addItem(text)
        self.setSelected(selected)