Run black

This commit is contained in:
Tom Tromey
2023-11-22 21:05:41 -07:00
parent 5da88dac7a
commit 602c144f6e
20 changed files with 365 additions and 280 deletions

View File

@@ -1,3 +1,4 @@
import sys import sys
sys.path.append('HERE')
sys.path.append("HERE")
import gui.commands import gui.commands

View File

@@ -24,18 +24,15 @@ bugs = {
15620: """Your gdb doesn't have a "new breakpoint" event. 15620: """Your gdb doesn't have a "new breakpoint" event.
This means that the source windows will not show you where This means that the source windows will not show you where
breakpoints have been set.""", breakpoints have been set.""",
13598: """Your gdb doesn't have a "before prompt" event. 13598: """Your gdb doesn't have a "before prompt" event.
This means that various windows won't be able to react to This means that various windows won't be able to react to
commands like "up" or "down".""", commands like "up" or "down".""",
18385: """Your gdb doesn't expose locations on a gdb.Breakpoint. 18385: """Your gdb doesn't expose locations on a gdb.Breakpoint.
This can be worked around, but maybe not always reliably. This can be worked around, but maybe not always reliably.
This means that sometimes breakpoints won't display in source windows.""", This means that sometimes breakpoints won't display in source windows.""",
18620: """Your gdb doesn't have a "breakpoint modified" event. 18620: """Your gdb doesn't have a "breakpoint modified" event.
This means that when a pending breakpoint is resolved, the GUI won't This means that when a pending breakpoint is resolved, the GUI won't
be able to update to reflect that fact.""" be able to update to reflect that fact.""",
} }
_warning = """See https://sourceware.org/bugzilla/show_bug.cgi?id=%s _warning = """See https://sourceware.org/bugzilla/show_bug.cgi?id=%s
@@ -43,6 +40,7 @@ for more information."""
_first_report = True _first_report = True
def notify_bug(bugno): def notify_bug(bugno):
if not gui.params.warn_missing.value: if not gui.params.warn_missing.value:
return return

View File

@@ -22,6 +22,7 @@ import gui.adapt
# destroyed. # destroyed.
_breakpoint_source_map = {} _breakpoint_source_map = {}
def _breakpoint_created(bp): def _breakpoint_created(bp):
if bp.location is None: if bp.location is None:
return return
@@ -45,6 +46,7 @@ def _breakpoint_created(bp):
else: else:
_breakpoint_source_map[entry].add(bp.number) _breakpoint_source_map[entry].add(bp.number)
def _breakpoint_deleted(bp): def _breakpoint_deleted(bp):
num = bp.number num = bp.number
for entry in _breakpoint_source_map: for entry in _breakpoint_source_map:
@@ -53,25 +55,28 @@ def _breakpoint_deleted(bp):
if len(_breakpoint_source_map[entry]) == 0: if len(_breakpoint_source_map[entry]) == 0:
gui.events.location_changed.post(entry, False) gui.events.location_changed.post(entry, False)
def _breakpoint_modified(bp): def _breakpoint_modified(bp):
if bp.enabled: if bp.enabled:
_breakpoint_created(bp) _breakpoint_created(bp)
else: else:
_breakpoint_deleted(bp) _breakpoint_deleted(bp)
def any_breakpoint_at(filename, lineno): def any_breakpoint_at(filename, lineno):
entry = (filename, lineno) entry = (filename, lineno)
if entry not in _breakpoint_source_map: if entry not in _breakpoint_source_map:
return False return False
return len(_breakpoint_source_map[entry]) > 0 return len(_breakpoint_source_map[entry]) > 0
if not hasattr(gdb.events, 'breakpoint_created'):
if not hasattr(gdb.events, "breakpoint_created"):
gui.adapt.notify_bug(15620) gui.adapt.notify_bug(15620)
else: else:
gdb.events.breakpoint_created.connect(_breakpoint_created) gdb.events.breakpoint_created.connect(_breakpoint_created)
gdb.events.breakpoint_deleted.connect(_breakpoint_deleted) gdb.events.breakpoint_deleted.connect(_breakpoint_deleted)
if not hasattr(gdb.events, 'breakpoint_modified'): if not hasattr(gdb.events, "breakpoint_modified"):
gui.adapt.notify_bug(18620) gui.adapt.notify_bug(18620)
else: else:
gdb.events.breakpoint_modified.connect(_breakpoint_modified) gdb.events.breakpoint_modified.connect(_breakpoint_modified)

View File

@@ -27,10 +27,11 @@ import gui.adapt
import re import re
from gui.startup import in_gtk_thread from gui.startup import in_gtk_thread
class GuiCommand(gdb.Command): class GuiCommand(gdb.Command):
def __init__(self): def __init__(self):
super(GuiCommand, self).__init__('gui', gdb.COMMAND_SUPPORT, super(GuiCommand, self).__init__("gui", gdb.COMMAND_SUPPORT, prefix=True)
prefix = True)
class GuiSourceCommand(gdb.Command): class GuiSourceCommand(gdb.Command):
"""Create a new source window. """Create a new source window.
@@ -39,21 +40,20 @@ This creates a new source window in the GUI. Any number of source
windows can be created.""" windows can be created."""
def __init__(self): def __init__(self):
super(GuiSourceCommand, self).__init__('gui source', super(GuiSourceCommand, self).__init__("gui source", gdb.COMMAND_SUPPORT)
gdb.COMMAND_SUPPORT)
def invoke(self, arg, from_tty): def invoke(self, arg, from_tty):
self.dont_repeat() self.dont_repeat()
gui.source.lru_handler.new_source_window() gui.source.lru_handler.new_source_window()
class GuiStackCommand(gdb.Command): class GuiStackCommand(gdb.Command):
"""Create a new stack window. """Create a new stack window.
Usage: gui stack Usage: gui stack
This creates a stack window in the GUI if it does not already exist.""" This creates a stack window in the GUI if it does not already exist."""
def __init__(self): def __init__(self):
super(GuiStackCommand, self).__init__('gui stack', super(GuiStackCommand, self).__init__("gui stack", gdb.COMMAND_SUPPORT)
gdb.COMMAND_SUPPORT)
def invoke(self, arg, from_tty): def invoke(self, arg, from_tty):
self.dont_repeat() self.dont_repeat()
@@ -64,6 +64,7 @@ This creates a stack window in the GUI if it does not already exist."""
# or maybe even whatever 'bt' takes? # or maybe even whatever 'bt' takes?
gui.stack.show_stack() gui.stack.show_stack()
class GuiListCommand(gdb.Command): class GuiListCommand(gdb.Command):
"""List some source code in a source window. """List some source code in a source window.
Usage: gui list LINESPEC Usage: gui list LINESPEC
@@ -73,24 +74,24 @@ displayed there. Otherwise, a new source window is made.
LINESPEC is a line specification of the form given to 'break'.""" LINESPEC is a line specification of the form given to 'break'."""
def __init__(self): def __init__(self):
super(GuiListCommand, self).__init__('gui list', super(GuiListCommand, self).__init__("gui list", gdb.COMMAND_SUPPORT)
gdb.COMMAND_SUPPORT)
def invoke(self, arg, from_tty): def invoke(self, arg, from_tty):
self.dont_repeat() self.dont_repeat()
(extra, sals) = gdb.decode_line(arg) (extra, sals) = gdb.decode_line(arg)
if extra is not None: if extra is not None:
raise gdb.GdbError('unrecognized junk at end of command: ' + extra) raise gdb.GdbError("unrecognized junk at end of command: " + extra)
if sals is None: if sals is None:
raise gdb.GdbError('not found') raise gdb.GdbError("not found")
if len(sals) > 1: if len(sals) > 1:
print("Ambiguous linespec, only showing first result") print("Ambiguous linespec, only showing first result")
sal = sals[0] sal = sals[0]
if sal.symtab is None or sal.symtab.filename is None: if sal.symtab is None or sal.symtab.filename is None:
raise gdb.GdbError('could not find file for symbol') raise gdb.GdbError("could not find file for symbol")
gui.source.lru_handler.show_source_gdb(None, sal.symtab, gui.source.lru_handler.show_source_gdb(
sal.symtab.fullname(), None, sal.symtab, sal.symtab.fullname(), sal.line
sal.line) )
class GuiShowCommand(gdb.Command): class GuiShowCommand(gdb.Command):
"""Show the source for a symbol in a source window. """Show the source for a symbol in a source window.
@@ -101,8 +102,7 @@ already available, the source is displayed there. Otherwise, a new
source window is made.""" source window is made."""
def __init__(self): def __init__(self):
super(GuiShowCommand, self).__init__('gui show', super(GuiShowCommand, self).__init__("gui show", gdb.COMMAND_SUPPORT)
gdb.COMMAND_SUPPORT)
def invoke(self, arg, from_tty): def invoke(self, arg, from_tty):
self.dont_repeat() self.dont_repeat()
@@ -113,13 +113,15 @@ source window is made."""
raise raise
symbol = gdb.lookup_global_symbol(arg) symbol = gdb.lookup_global_symbol(arg)
if symbol is None: if symbol is None:
raise gdb.GdbError('symbol ' + arg + ' not found') raise gdb.GdbError("symbol " + arg + " not found")
if symbol.symtab is None or symbol.symtab.filename is None: if symbol.symtab is None or symbol.symtab.filename is None:
raise gdb.GdbError('symbol ' + arg raise gdb.GdbError(
+ ' does not seem to have an associated file') "symbol " + arg + " does not seem to have an associated file"
gui.source.lru_handler.show_source_gdb(None, symbol.symtab, )
symbol.symtab.fullname(), gui.source.lru_handler.show_source_gdb(
symbol.line) None, symbol.symtab, symbol.symtab.fullname(), symbol.line
)
class GuiLogWindowCommand(gdb.Command): class GuiLogWindowCommand(gdb.Command):
"""Create a new log window. """Create a new log window.
@@ -134,53 +136,55 @@ a given instance using the "@" syntax, like:
gui print @5 variable""" gui print @5 variable"""
def __init__(self): def __init__(self):
super(GuiLogWindowCommand, self).__init__('gui log', super(GuiLogWindowCommand, self).__init__("gui log", gdb.COMMAND_SUPPORT)
gdb.COMMAND_SUPPORT)
def invoke(self, arg, from_tty): def invoke(self, arg, from_tty):
self.dont_repeat() self.dont_repeat()
window = gui.logwindow.LogWindow() window = gui.logwindow.LogWindow()
print("Created log window %d; now the default" % window.number) print("Created log window %d; now the default" % window.number)
class GuiPrintBase(gdb.Command): class GuiPrintBase(gdb.Command):
def __init__(self, command): def __init__(self, command):
super(GuiPrintBase, self).__init__('gui ' + command, super(GuiPrintBase, self).__init__("gui " + command, gdb.COMMAND_SUPPORT)
gdb.COMMAND_SUPPORT)
self.command = command self.command = command
# Given ARG, return a pair (WINDOW, NEW_ARG). # Given ARG, return a pair (WINDOW, NEW_ARG).
def _parse_arg(self, arg, do_default=True): def _parse_arg(self, arg, do_default=True):
arg = arg.strip() arg = arg.strip()
match = re.match('@(\\d+)\\s+(.*)$', arg) match = re.match("@(\\d+)\\s+(.*)$", arg)
if match is not None: if match is not None:
winno = int(match.group(1)) winno = int(match.group(1))
arg = match.group(2) arg = match.group(2)
window = gui.toplevel.state.get(winno) window = gui.toplevel.state.get(winno)
if window is None: if window is None:
raise gdb.GdbError('could not find window %d' % winno) raise gdb.GdbError("could not find window %d" % winno)
if not isinstance(window, gui.logwindow.LogWindow): if not isinstance(window, gui.logwindow.LogWindow):
raise gdb.GdbError('window %d is not a log window' % winno) raise gdb.GdbError("window %d is not a log window" % winno)
elif do_default: elif do_default:
window = gui.logwindow.default_log_window window = gui.logwindow.default_log_window
if window is None: if window is None:
raise gdb.GdbError('no default log window') raise gdb.GdbError("no default log window")
else: else:
window = None window = None
return (window, arg) return (window, arg)
def invoke(self, arg, from_tty): def invoke(self, arg, from_tty):
(window, arg) = self._parse_arg(arg) (window, arg) = self._parse_arg(arg)
text = gdb.execute(self.command + ' ' + arg, from_tty, True) text = gdb.execute(self.command + " " + arg, from_tty, True)
window.append(text) window.append(text)
class GuiPrintCommand(GuiPrintBase): class GuiPrintCommand(GuiPrintBase):
"""Print to a gui log window. """Print to a gui log window.
Usage: gui print [@N] ARGS Usage: gui print [@N] ARGS
This is a wrapper for the "print" command that redirects its output This is a wrapper for the "print" command that redirects its output
to a "gui log" window. If "@N" is given, then output goes to that to a "gui log" window. If "@N" is given, then output goes to that
window; otherwise, output goes to the most recently created log window.""" window; otherwise, output goes to the most recently created log window."""
def __init__(self): def __init__(self):
super(GuiPrintCommand, self).__init__('print') super(GuiPrintCommand, self).__init__("print")
class GuiOutputCommand(GuiPrintBase): class GuiOutputCommand(GuiPrintBase):
"""Output to a gui log window. """Output to a gui log window.
@@ -188,8 +192,10 @@ Usage: gui output [@N] ARGS
This is a wrapper for the "output" command that redirects its output This is a wrapper for the "output" command that redirects its output
to a "gui log" window. If "@N" is given, then output goes to that to a "gui log" window. If "@N" is given, then output goes to that
window; otherwise, output goes to the most recently created log window.""" window; otherwise, output goes to the most recently created log window."""
def __init__(self): def __init__(self):
super(GuiOutputCommand, self).__init__('output') super(GuiOutputCommand, self).__init__("output")
class GuiPrintfCommand(GuiPrintBase): class GuiPrintfCommand(GuiPrintBase):
"""printf to a gui log window. """printf to a gui log window.
@@ -197,8 +203,10 @@ Usage: gui printf [@N] ARGS
This is a wrapper for the "printf" command that redirects its output This is a wrapper for the "printf" command that redirects its output
to a "gui log" window. If "@N" is given, then output goes to that to a "gui log" window. If "@N" is given, then output goes to that
window; otherwise, output goes to the most recently created log window.""" window; otherwise, output goes to the most recently created log window."""
def __init__(self): def __init__(self):
super(GuiPrintfCommand, self).__init__('printf') super(GuiPrintfCommand, self).__init__("printf")
class GuiDprintfCommand(GuiPrintBase): class GuiDprintfCommand(GuiPrintBase):
"""dprintf to a gui log window. """dprintf to a gui log window.
@@ -206,8 +214,9 @@ Usage: gui dprintf [@N] ARGS
This is a wrapper for the "dprintf" command that redirects its output This is a wrapper for the "dprintf" command that redirects its output
to a "gui log" window. If "@N" is given, then output goes to that to a "gui log" window. If "@N" is given, then output goes to that
window; otherwise, output goes to the most recently created log window.""" window; otherwise, output goes to the most recently created log window."""
def __init__(self): def __init__(self):
super(GuiDprintfCommand, self).__init__('dprintf') super(GuiDprintfCommand, self).__init__("dprintf")
def invoke(self, arg, from_tty): def invoke(self, arg, from_tty):
(window, arg) = self._parse_arg(arg, False) (window, arg) = self._parse_arg(arg, False)
@@ -216,12 +225,13 @@ window; otherwise, output goes to the most recently created log window."""
if arg is None: if arg is None:
raise gdb.GdbError("no printf arguments to 'gui dprintf'") raise gdb.GdbError("no printf arguments to 'gui dprintf'")
arg = arg.strip() arg = arg.strip()
if not arg.startswith(','): if not arg.startswith(","):
raise gdb.GdbError("comma expected after linespec") raise gdb.GdbError("comma expected after linespec")
arg = arg[1:] arg = arg[1:]
spec = arg[0 : -len(arg)] spec = arg[0 : -len(arg)]
DPrintfBreakpoint(spec, window, arg) DPrintfBreakpoint(spec, window, arg)
class GuiDisplayCommand(gdb.Command): class GuiDisplayCommand(gdb.Command):
"""Create a new display window. """Create a new display window.
Usage: gui display [-diff] COMMAND Usage: gui display [-diff] COMMAND
@@ -232,13 +242,12 @@ given, then every time the display is updated, changed lines are
highlighted.""" highlighted."""
def __init__(self): def __init__(self):
super(GuiDisplayCommand, self).__init__('gui display', super(GuiDisplayCommand, self).__init__("gui display", gdb.COMMAND_SUPPORT)
gdb.COMMAND_SUPPORT)
def invoke(self, arg, from_tty): def invoke(self, arg, from_tty):
self.dont_repeat() self.dont_repeat()
diff = False diff = False
if arg.startswith('-diff '): if arg.startswith("-diff "):
diff = True diff = True
arg = arg[6:] arg = arg[6:]
gui.display.DisplayWindow(arg, diff) gui.display.DisplayWindow(arg, diff)
@@ -248,6 +257,7 @@ highlighted."""
# https://sourceware.org/bugzilla/show_bug.cgi?id=13077 # https://sourceware.org/bugzilla/show_bug.cgi?id=13077
return None return None
class InfoWindowsCommand(gdb.Command): class InfoWindowsCommand(gdb.Command):
"""List all the GUI windows. """List all the GUI windows.
Usage: info windows Usage: info windows
@@ -256,13 +266,13 @@ Note that this should not be confused with "info win", which is
part of the TUI.""" part of the TUI."""
def __init__(self): def __init__(self):
super(InfoWindowsCommand, self).__init__('info windows', super(InfoWindowsCommand, self).__init__("info windows", gdb.COMMAND_SUPPORT)
gdb.COMMAND_SUPPORT)
def invoke(self, arg, from_tty): def invoke(self, arg, from_tty):
self.dont_repeat() self.dont_repeat()
gui.toplevel.state.display() gui.toplevel.state.display()
class DeleteWindowsCommand(gdb.Command): class DeleteWindowsCommand(gdb.Command):
"""Delete a GUI window. """Delete a GUI window.
Usage: delete window N Usage: delete window N
@@ -271,8 +281,7 @@ A window's number appears in its title bar, and can also be
found using "info windows".""" found using "info windows"."""
def __init__(self): def __init__(self):
super(DeleteWindowsCommand, self).__init__('delete window', super(DeleteWindowsCommand, self).__init__("delete window", gdb.COMMAND_SUPPORT)
gdb.COMMAND_SUPPORT)
def invoke(self, arg, from_tty): def invoke(self, arg, from_tty):
self.dont_repeat() self.dont_repeat()
@@ -281,6 +290,7 @@ found using "info windows"."""
if window is not None: if window is not None:
window.destroy() window.destroy()
GuiCommand() GuiCommand()
GuiSourceCommand() GuiSourceCommand()
GuiStackCommand() GuiStackCommand()
@@ -304,7 +314,7 @@ class TestCommand(gdb.Command):
your copy of gdb has some command-overriding support.""" your copy of gdb has some command-overriding support."""
def __init__(self, set_it): def __init__(self, set_it):
super(TestCommand, self).__init__('maint gui-test', gdb.COMMAND_DATA) super(TestCommand, self).__init__("maint gui-test", gdb.COMMAND_DATA)
self.set_it = set_it self.set_it = set_it
def invoke(self, arg, from_tty): def invoke(self, arg, from_tty):
@@ -317,13 +327,15 @@ class TestCommand(gdb.Command):
except: except:
pass pass
TestCommand(True) TestCommand(True)
TestCommand(False).invoke('', 0) TestCommand(False).invoke("", 0)
# See framecache.py - we prefer the before_prompt event if it exists; # See framecache.py - we prefer the before_prompt event if it exists;
# but otherwise try the overriding approach. Both of these rely on a # but otherwise try the overriding approach. Both of these rely on a
# hacked gdb :-( # hacked gdb :-(
if _can_override and not hasattr(gdb.events, 'before_prompt'): if _can_override and not hasattr(gdb.events, "before_prompt"):
class Overrider(gdb.Command): class Overrider(gdb.Command):
def __init__(self, name, event): def __init__(self, name, event):
super(Overrider, self).__init__(name, gdb.COMMAND_DATA) super(Overrider, self).__init__(name, gdb.COMMAND_DATA)
@@ -333,6 +345,6 @@ if _can_override and not hasattr(gdb.events, 'before_prompt'):
super(Overrider, self).invoke(arg, from_tty) super(Overrider, self).invoke(arg, from_tty)
self.event.post() self.event.post()
Overrider('up', gui.events.frame_changed) Overrider("up", gui.events.frame_changed)
Overrider('down', gui.events.frame_changed) Overrider("down", gui.events.frame_changed)
Overrider('frame', gui.events.frame_changed) Overrider("frame", gui.events.frame_changed)

View File

@@ -27,12 +27,13 @@ from difflib import SequenceMatcher, Differ
# FIXME: TO DO: # FIXME: TO DO:
# * highlight the changes # * highlight the changes
class DisplayWindow(gui.updatewindow.UpdateWindow): class DisplayWindow(gui.updatewindow.UpdateWindow):
def __init__(self, command, diff=False): def __init__(self, command, diff=False):
self.command = command self.command = command
self.diff = diff self.diff = diff
self.last_text = None self.last_text = None
super(DisplayWindow, self).__init__('display') super(DisplayWindow, self).__init__("display")
@in_gdb_thread @in_gdb_thread
def on_event(self): def on_event(self):
@@ -44,21 +45,20 @@ class DisplayWindow(gui.updatewindow.UpdateWindow):
@in_gtk_thread @in_gtk_thread
def gtk_initialize(self): def gtk_initialize(self):
builder = gui.startup.create_builder('logwindow.xml') builder = gui.startup.create_builder("logwindow.xml")
builder.connect_signals(self) builder.connect_signals(self)
self.window = builder.get_object('logwindow') self.window = builder.get_object("logwindow")
self.view = builder.get_object('textview') self.view = builder.get_object("textview")
self.view.modify_font(Pango.FontDescription('Fixed')) self.view.modify_font(Pango.FontDescription("Fixed"))
self.buffer = builder.get_object('buffer') self.buffer = builder.get_object("buffer")
if self.diff: if self.diff:
self.tag = self.buffer.create_tag('new', foreground = 'red') self.tag = self.buffer.create_tag("new", foreground="red")
def _update(self, text): def _update(self, text):
self.buffer.delete(self.buffer.get_start_iter(), self.buffer.delete(self.buffer.get_start_iter(), self.buffer.get_end_iter())
self.buffer.get_end_iter())
if self.diff: if self.diff:
if self.last_text is None: if self.last_text is None:
self.last_text = text.splitlines(1) self.last_text = text.splitlines(1)
@@ -67,14 +67,13 @@ class DisplayWindow(gui.updatewindow.UpdateWindow):
split = text.splitlines(1) split = text.splitlines(1)
d = Differ() d = Differ()
for line in d.compare(self.last_text, split): for line in d.compare(self.last_text, split):
if line[0] == ' ': if line[0] == " ":
self.buffer.insert(self.buffer.get_end_iter(), self.buffer.insert(self.buffer.get_end_iter(), line[2:])
line[2:]) elif line[0] == "+":
elif line[0] == '+': self.buffer.insert_with_tags(
self.buffer.insert_with_tags(self.buffer.get_end_iter(), self.buffer.get_end_iter(), line[2:], self.tag
line[2:], )
self.tag) self.buffer.insert(self.buffer.get_end_iter(), "\n")
self.buffer.insert(self.buffer.get_end_iter(), '\n')
self.last_text = split self.last_text = split
return return
self.buffer.insert_at_cursor(text) self.buffer.insert_at_cursor(text)

View File

@@ -19,12 +19,13 @@ import gdb
import gui.logwindow import gui.logwindow
from gui.startup import in_gdb_thread from gui.startup import in_gdb_thread
class DPrintfBreakpoint(gdb.Breakpoint): class DPrintfBreakpoint(gdb.Breakpoint):
@in_gdb_thread @in_gdb_thread
def __init__(self, spec, window, arg): def __init__(self, spec, window, arg):
super(DPrintfBreakpoint, self).__init__(spec, gdb.BP_BREAKPOINT) super(DPrintfBreakpoint, self).__init__(spec, gdb.BP_BREAKPOINT)
self.window = window self.window = window
self.command = 'printf ' + arg self.command = "printf " + arg
@in_gdb_thread @in_gdb_thread
def stop(self): def stop(self):

View File

@@ -15,6 +15,7 @@
import gdb import gdb
class _Event(object): class _Event(object):
def __init__(self): def __init__(self):
self.funcs = [] self.funcs = []
@@ -29,5 +30,6 @@ class _Event(object):
for fun in self.funcs: for fun in self.funcs:
fun(*args, **kwargs) fun(*args, **kwargs)
frame_changed = _Event() frame_changed = _Event()
location_changed = _Event() location_changed = _Event()

View File

@@ -22,6 +22,7 @@ from gui.startup import in_gdb_thread
_last_selected_frame = None _last_selected_frame = None
def check_frame(): def check_frame():
global _last_selected_frame global _last_selected_frame
sel = None sel = None
@@ -33,6 +34,7 @@ def check_frame():
_last_selected_frame = sel _last_selected_frame = sel
gui.events.frame_changed.post() gui.events.frame_changed.post()
# We need this because we rely on the before_prompt hook to notify us # We need this because we rely on the before_prompt hook to notify us
# of frame changes. A dedicated frame change hook would be better. # of frame changes. A dedicated frame change hook would be better.
class FrameCommandInvoker(gui.invoker.Invoker): class FrameCommandInvoker(gui.invoker.Invoker):
@@ -41,8 +43,9 @@ class FrameCommandInvoker(gui.invoker.Invoker):
gui.invoker.Invoker.do_call(self) gui.invoker.Invoker.do_call(self)
check_frame() check_frame()
# See my gdb branch on github. # See my gdb branch on github.
if hasattr(gdb.events, 'before_prompt'): if hasattr(gdb.events, "before_prompt"):
gdb.events.before_prompt.connect(check_frame) gdb.events.before_prompt.connect(check_frame)
else: else:
gui.adapt.notify_bug(13598) gui.adapt.notify_bug(13598)

View File

@@ -24,16 +24,18 @@ gui_prompt_substitutions = dict(gdb.prompt.prompt_substitutions)
_current_window_for_prompt = None _current_window_for_prompt = None
def _prompt_window(attr): def _prompt_window(attr):
if _current_window_for_prompt is None: if _current_window_for_prompt is None:
return '' return ""
if attr is None: if attr is None:
return '' return ""
if not hasattr(_current_window_for_prompt, attr): if not hasattr(_current_window_for_prompt, attr):
return None return None
return str(getattr(_current_window_for_prompt, attr)) return str(getattr(_current_window_for_prompt, attr))
gui_prompt_substitutions['W'] = _prompt_window
gui_prompt_substitutions["W"] = _prompt_window
# GDB's API should do this... # GDB's API should do this...
def substitute_prompt_with_window(prompt, window): def substitute_prompt_with_window(prompt, window):
@@ -49,6 +51,7 @@ def substitute_prompt_with_window(prompt, window):
_current_window_for_prompt = None _current_window_for_prompt = None
return result return result
# GDB's API should do this... # GDB's API should do this...
def prompt_help_with_window(window): def prompt_help_with_window(window):
global _current_window_for_prompt global _current_window_for_prompt
@@ -63,6 +66,7 @@ def prompt_help_with_window(window):
_current_window_for_prompt = None _current_window_for_prompt = None
return result return result
@in_gdb_thread @in_gdb_thread
def is_running(): def is_running():
"""Return True if the inferior is running.""" """Return True if the inferior is running."""

View File

@@ -16,6 +16,7 @@
import gdb import gdb
from gui.startup import in_gdb_thread from gui.startup import in_gdb_thread
class Invoker(object): class Invoker(object):
"""A simple class that can invoke a gdb command. """A simple class that can invoke a gdb command.
This is suitable for use as an event handler in Gtk.""" This is suitable for use as an event handler in Gtk."""

View File

@@ -25,25 +25,26 @@ from gui.startup import in_gtk_thread
default_log_window = None default_log_window = None
class LogWindow(gui.toplevel.Toplevel): class LogWindow(gui.toplevel.Toplevel):
def __init__(self): def __init__(self):
global default_log_window global default_log_window
if default_log_window is not None: if default_log_window is not None:
default_log_window.default = '' default_log_window.default = ""
default_log_window = self default_log_window = self
# For the window title. # For the window title.
self.default = ' [Default]' self.default = " [Default]"
super(LogWindow, self).__init__('log') super(LogWindow, self).__init__("log")
@in_gtk_thread @in_gtk_thread
def gtk_initialize(self): def gtk_initialize(self):
builder = gui.startup.create_builder('logwindow.xml') builder = gui.startup.create_builder("logwindow.xml")
builder.connect_signals(self) builder.connect_signals(self)
self.window = builder.get_object('logwindow') self.window = builder.get_object("logwindow")
self.view = builder.get_object('textview') self.view = builder.get_object("textview")
self.view.modify_font(gui.params.font_manager.get_font()) self.view.modify_font(gui.params.font_manager.get_font())
self.buffer = builder.get_object('buffer') self.buffer = builder.get_object("buffer")
@in_gtk_thread @in_gtk_thread
def set_font(self, font): def set_font(self, font):
@@ -56,7 +57,7 @@ class LogWindow(gui.toplevel.Toplevel):
for window in gui.toplevel.state.windows(): for window in gui.toplevel.state.windows():
if isinstance(window, LogWindow): if isinstance(window, LogWindow):
default_log_window = window default_log_window = window
window.default = ' [Default]' window.default = " [Default]"
window.update_title() window.update_title()
break break

View File

@@ -27,6 +27,7 @@ _initialized = False
_last_time = None _last_time = None
@in_gtk_thread @in_gtk_thread
def _show_notification(title, content): def _show_notification(title, content):
global _initialized global _initialized
@@ -36,41 +37,45 @@ def _show_notification(title, content):
n = Notify.Notification.new(title, content) n = Notify.Notification.new(title, content)
n.show() n.show()
@in_gdb_thread @in_gdb_thread
def _on_stop(event): def _on_stop(event):
global _last_time global _last_time
t = _last_time t = _last_time
_last_time = None _last_time = None
if (t is None if (
t is None
or not gui.params.stop_notification.value or not gui.params.stop_notification.value
or time.process_time() - t < gui.params.stop_notification_seconds.value): or time.process_time() - t < gui.params.stop_notification_seconds.value
):
return return
if isinstance(event, gdb.ExitedEvent): if isinstance(event, gdb.ExitedEvent):
title = 'gdb - inferior exited' title = "gdb - inferior exited"
if hasattr(event, 'exit_code'): if hasattr(event, "exit_code"):
content = 'inferior exited with code ' + str(event.exit_code) content = "inferior exited with code " + str(event.exit_code)
else: else:
content = 'inferior exited, code unavailable' content = "inferior exited, code unavailable"
elif isinstance(event, gdb.BreakpointEvent): elif isinstance(event, gdb.BreakpointEvent):
title = 'gdb - inferior stopped' title = "gdb - inferior stopped"
content = ('inferior stopped at breakpoint ' content = "inferior stopped at breakpoint " + str(event.breakpoints[0].number)
+ str(event.breakpoints[0].number))
elif isinstance(event, gdb.SignalEvent): elif isinstance(event, gdb.SignalEvent):
title = 'gdb - inferior stopped' title = "gdb - inferior stopped"
content = 'inferior stopped with signal: ' + event.stop_signal content = "inferior stopped with signal: " + event.stop_signal
else: else:
title = 'gdb - inferior stopped' title = "gdb - inferior stopped"
content = 'inferior stopped, reason unknown' content = "inferior stopped, reason unknown"
gui.startup.send_to_gtk(lambda: _show_notification(title, content)) gui.startup.send_to_gtk(lambda: _show_notification(title, content))
@in_gdb_thread @in_gdb_thread
def _on_cont(event): def _on_cont(event):
global _last_time global _last_time
_last_time = time.process_time() _last_time = time.process_time()
gdb.events.stop.connect(_on_stop) gdb.events.stop.connect(_on_stop)
gdb.events.cont.connect(_on_cont) gdb.events.cont.connect(_on_cont)
gdb.events.exited.connect(_on_stop) gdb.events.exited.connect(_on_stop)

View File

@@ -24,33 +24,38 @@ import gui.toplevel
from gui.startup import in_gdb_thread, in_gtk_thread from gui.startup import in_gdb_thread, in_gtk_thread
from gi.repository import GtkSource, Pango from gi.repository import GtkSource, Pango
class _SetBase(gdb.Command): class _SetBase(gdb.Command):
"""Generic command for modifying GUI settings.""" """Generic command for modifying GUI settings."""
def __init__(self): def __init__(self):
super(_SetBase, self).__init__('set gui', gdb.COMMAND_NONE, super(_SetBase, self).__init__("set gui", gdb.COMMAND_NONE, prefix=True)
prefix = True)
class _SetTitleBase(gdb.Command): class _SetTitleBase(gdb.Command):
"""Generic command for modifying GUI window titles.""" """Generic command for modifying GUI window titles."""
def __init__(self): def __init__(self):
super(_SetTitleBase, self).__init__('set gui title', gdb.COMMAND_NONE, super(_SetTitleBase, self).__init__(
prefix = True) "set gui title", gdb.COMMAND_NONE, prefix=True
)
class _ShowBase(gdb.Command): class _ShowBase(gdb.Command):
"""Generic command for showing GUI settings.""" """Generic command for showing GUI settings."""
def __init__(self): def __init__(self):
super(_ShowBase, self).__init__('show gui', gdb.COMMAND_NONE, super(_ShowBase, self).__init__("show gui", gdb.COMMAND_NONE, prefix=True)
prefix = True)
class _ShowTitleBase(gdb.Command): class _ShowTitleBase(gdb.Command):
"""Generic command for showing GUI window titles.""" """Generic command for showing GUI window titles."""
def __init__(self): def __init__(self):
super(_ShowTitleBase, self).__init__('show gui title', gdb.COMMAND_NONE, super(_ShowTitleBase, self).__init__(
prefix = True) "show gui title", gdb.COMMAND_NONE, prefix=True
)
# Like gdb.Parameter, but has a default and automatically handles # Like gdb.Parameter, but has a default and automatically handles
# storage. # storage.
@@ -58,11 +63,10 @@ class _StoredParameter(gdb.Parameter):
# NAME_FORMAT is like "%s" - NAME is substituted. # NAME_FORMAT is like "%s" - NAME is substituted.
# To construct the parameter name, "gui " is prefixed. # To construct the parameter name, "gui " is prefixed.
def __init__(self, name_format, name, default, c_class, p_kind, *args): def __init__(self, name_format, name, default, c_class, p_kind, *args):
full_name = 'gui ' + name_format % name full_name = "gui " + name_format % name
self.storage_name = '-'.join((name_format % name).split(' ')) self.storage_name = "-".join((name_format % name).split(" "))
storage = gui.storage.storage_manager storage = gui.storage.storage_manager
super(_StoredParameter, self).__init__(full_name, c_class, p_kind, super(_StoredParameter, self).__init__(full_name, c_class, p_kind, *args)
*args)
if p_kind is gdb.PARAM_BOOLEAN: if p_kind is gdb.PARAM_BOOLEAN:
val = storage.getboolean(self.storage_name) val = storage.getboolean(self.storage_name)
elif p_kind is gdb.PARAM_STRING or p_kind is gdb.PARAM_ENUM: elif p_kind is gdb.PARAM_STRING or p_kind is gdb.PARAM_ENUM:
@@ -87,19 +91,25 @@ class _StoredParameter(gdb.Parameter):
self.storage.set(self.storage_name, self.value) self.storage.set(self.storage_name, self.value)
return "" return ""
class _Theme(_StoredParameter): class _Theme(_StoredParameter):
# Silly gdb requirement. # Silly gdb requirement.
"" """"""
set_doc = "Set the source window theme." set_doc = "Set the source window theme."
show_doc = "Show the source window theme." show_doc = "Show the source window theme."
def __init__(self): def __init__(self):
self.manager = GtkSource.StyleSchemeManager.get_default() self.manager = GtkSource.StyleSchemeManager.get_default()
super(_Theme, self).__init__('%s', 'theme', None, super(_Theme, self).__init__(
gdb.COMMAND_NONE, gdb.PARAM_ENUM, "%s",
"theme",
None,
gdb.COMMAND_NONE,
gdb.PARAM_ENUM,
# Probably the wrong thread. # Probably the wrong thread.
self.manager.get_scheme_ids()) self.manager.get_scheme_ids(),
)
@in_gdb_thread @in_gdb_thread
def set_buffer_manager(self, b): def set_buffer_manager(self, b):
@@ -120,17 +130,19 @@ class _Theme(_StoredParameter):
self.buffer_manager.change_theme() self.buffer_manager.change_theme()
return "" return ""
class _Font(_StoredParameter): class _Font(_StoredParameter):
# Silly gdb requirement. # Silly gdb requirement.
"" """"""
set_doc = "Set the source window font." set_doc = "Set the source window font."
show_doc = "Show the source window font." show_doc = "Show the source window font."
def __init__(self): def __init__(self):
self.manager = GtkSource.StyleSchemeManager.get_default() self.manager = GtkSource.StyleSchemeManager.get_default()
super(_Font, self).__init__('%s', 'font', 'monospace', super(_Font, self).__init__(
gdb.COMMAND_NONE, gdb.PARAM_STRING) "%s", "font", "monospace", gdb.COMMAND_NONE, gdb.PARAM_STRING
)
@in_gtk_thread @in_gtk_thread
def get_font(self): def get_font(self):
@@ -147,11 +159,13 @@ class _Font(_StoredParameter):
super(_Font, self).get_set_string() super(_Font, self).get_set_string()
return "" return ""
title_params = {} title_params = {}
class _Title(_StoredParameter): class _Title(_StoredParameter):
# Silly gdb requirement. # Silly gdb requirement.
"" """"""
def __init__(self, name, default): def __init__(self, name, default):
title_params[name] = self title_params[name] = self
@@ -159,9 +173,10 @@ class _Title(_StoredParameter):
self.set_doc = "Set the %s window title format." % self.name self.set_doc = "Set the %s window title format." % self.name
self.show_doc = "Show the %s window title format." % self.name self.show_doc = "Show the %s window title format." % self.name
self.manager = GtkSource.StyleSchemeManager.get_default() self.manager = GtkSource.StyleSchemeManager.get_default()
super(_Title, self).__init__('title %s', name, default, super(_Title, self).__init__(
gdb.COMMAND_NONE, gdb.PARAM_STRING) "title %s", name, default, gdb.COMMAND_NONE, gdb.PARAM_STRING
val = self.storage.get('title-%s' % name) )
val = self.storage.get("title-%s" % name)
if val is not None: if val is not None:
self.value = val self.value = val
else: else:
@@ -169,8 +184,7 @@ class _Title(_StoredParameter):
@in_gdb_thread @in_gdb_thread
def get_show_string(self, pvalue): def get_show_string(self, pvalue):
return "The current title format for the %s is: %s" % (self.name, return "The current title format for the %s is: %s" % (self.name, self.value)
self.value)
@in_gdb_thread @in_gdb_thread
def get_set_string(self): def get_set_string(self):
@@ -178,16 +192,18 @@ class _Title(_StoredParameter):
gui.toplevel.state.update_titles() gui.toplevel.state.update_titles()
return "" return ""
class _Missing(_StoredParameter): class _Missing(_StoredParameter):
# Silly gdb requirement. # Silly gdb requirement.
"" """"""
set_doc = "Set whether to mention missing gdb features." set_doc = "Set whether to mention missing gdb features."
show_doc = "Show whether to mention missing gdb features." show_doc = "Show whether to mention missing gdb features."
def __init__(self): def __init__(self):
super(_Missing, self).__init__('%s', 'mention-missing', True, super(_Missing, self).__init__(
gdb.COMMAND_NONE, gdb.PARAM_BOOLEAN) "%s", "mention-missing", True, gdb.COMMAND_NONE, gdb.PARAM_BOOLEAN
)
@in_gdb_thread @in_gdb_thread
def get_show_string(self, pvalue): def get_show_string(self, pvalue):
@@ -197,21 +213,22 @@ class _Missing(_StoredParameter):
v = "off" v = "off"
return "Whether to warn about missing gdb features: " + v return "Whether to warn about missing gdb features: " + v
class _Lines(_StoredParameter): class _Lines(_StoredParameter):
# Silly gdb requirement. # Silly gdb requirement.
"" """"""
set_doc = "Set whether to display line numbers in the source window." set_doc = "Set whether to display line numbers in the source window."
show_doc = "Show whether to display line numbers in the source window." show_doc = "Show whether to display line numbers in the source window."
def __init__(self): def __init__(self):
super(_Lines, self).__init__('%s', 'line-numbers', False, super(_Lines, self).__init__(
gdb.COMMAND_NONE, gdb.PARAM_BOOLEAN) "%s", "line-numbers", False, gdb.COMMAND_NONE, gdb.PARAM_BOOLEAN
)
@in_gdb_thread @in_gdb_thread
def get_show_string(self, pvalue): def get_show_string(self, pvalue):
return "The current title format for the %s is: %s" % (self.name, return "The current title format for the %s is: %s" % (self.name, self.value)
self.value)
@in_gdb_thread @in_gdb_thread
def get_set_string(self): def get_set_string(self):
@@ -219,20 +236,24 @@ class _Lines(_StoredParameter):
gui.toplevel.state.set_line_numbers(self.value) gui.toplevel.state.set_line_numbers(self.value)
return "" return ""
class _Lines(_StoredParameter): class _Lines(_StoredParameter):
# Silly gdb requirement. # Silly gdb requirement.
"" """"""
set_doc = "Set whether to display line numbers in the source window." set_doc = "Set whether to display line numbers in the source window."
show_doc = "Show whether to display line numbers in the source window." show_doc = "Show whether to display line numbers in the source window."
def __init__(self): def __init__(self):
super(_Lines, self).__init__('%s', 'line-numbers', False, super(_Lines, self).__init__(
gdb.COMMAND_NONE, gdb.PARAM_BOOLEAN) "%s", "line-numbers", False, gdb.COMMAND_NONE, gdb.PARAM_BOOLEAN
)
@in_gdb_thread @in_gdb_thread
def get_show_string(self, pvalue): def get_show_string(self, pvalue):
return "Whether to display line numbers in the source window is: %s" % self.value return (
"Whether to display line numbers in the source window is: %s" % self.value
)
@in_gdb_thread @in_gdb_thread
def get_set_string(self): def get_set_string(self):
@@ -240,16 +261,18 @@ class _Lines(_StoredParameter):
gui.toplevel.state.set_line_numbers(self.value) gui.toplevel.state.set_line_numbers(self.value)
return "" return ""
class _Tabs(_StoredParameter): class _Tabs(_StoredParameter):
# Silly gdb requirement. # Silly gdb requirement.
"" """"""
set_doc = "Set width of tabs in the source window." set_doc = "Set width of tabs in the source window."
show_doc = "Show width of tabs in the source window." show_doc = "Show width of tabs in the source window."
def __init__(self): def __init__(self):
super(_Tabs, self).__init__('%s', 'tab-width', 8, super(_Tabs, self).__init__(
gdb.COMMAND_NONE, gdb.PARAM_ZINTEGER) "%s", "tab-width", 8, gdb.COMMAND_NONE, gdb.PARAM_ZINTEGER
)
@in_gdb_thread @in_gdb_thread
def get_show_string(self, pvalue): def get_show_string(self, pvalue):
@@ -261,40 +284,45 @@ class _Tabs(_StoredParameter):
gui.toplevel.state.set_tab_width(self.value) gui.toplevel.state.set_tab_width(self.value)
return "" return ""
class _StopNotification(_StoredParameter): class _StopNotification(_StoredParameter):
# Silly gdb requirement. # Silly gdb requirement.
"" """"""
set_doc = "Set whether stop notifications are displayed." set_doc = "Set whether stop notifications are displayed."
show_doc = "Show whether stop notifications are displayed." show_doc = "Show whether stop notifications are displayed."
def __init__(self): def __init__(self):
super(_StopNotification, self).__init__('%s', 'stop-notification', True, super(_StopNotification, self).__init__(
gdb.COMMAND_RUNNING, "%s", "stop-notification", True, gdb.COMMAND_RUNNING, gdb.PARAM_BOOLEAN
gdb.PARAM_BOOLEAN) )
@in_gdb_thread @in_gdb_thread
def get_show_string(self, pvalue): def get_show_string(self, pvalue):
return "Whether stop notifications are displayed is: %s" % self.value return "Whether stop notifications are displayed is: %s" % self.value
class _StopNotificationSeconds(_StoredParameter): class _StopNotificationSeconds(_StoredParameter):
# Silly gdb requirement. # Silly gdb requirement.
"" """"""
set_doc = "Set stop notification timeout in seconds." set_doc = "Set stop notification timeout in seconds."
show_doc = "Show stop notification timeout." show_doc = "Show stop notification timeout."
def __init__(self): def __init__(self):
super(_StopNotificationSeconds, self).__init__('%s', super(_StopNotificationSeconds, self).__init__(
'stop-notification-seconds', "%s",
"stop-notification-seconds",
120, 120,
gdb.COMMAND_RUNNING, gdb.COMMAND_RUNNING,
gdb.PARAM_ZINTEGER) gdb.PARAM_ZINTEGER,
)
@in_gdb_thread @in_gdb_thread
def get_show_string(self, pvalue): def get_show_string(self, pvalue):
return "Stop notifications are displayed after %d seconds." % self.value return "Stop notifications are displayed after %d seconds." % self.value
_SetBase() _SetBase()
_SetTitleBase() _SetTitleBase()
_ShowBase() _ShowBase()
@@ -304,10 +332,10 @@ font_manager = _Font()
stop_notification = _StopNotification() stop_notification = _StopNotification()
stop_notification_seconds = _StopNotificationSeconds() stop_notification_seconds = _StopNotificationSeconds()
_Title('source', '\\W{basename} [GDB Source @\\W{number}]') _Title("source", "\\W{basename} [GDB Source @\\W{number}]")
_Title('display', '\\W{command} [GDB Display @\\W{number}]') _Title("display", "\\W{command} [GDB Display @\\W{number}]")
_Title('log', '[GDB Log @\\W{number}]\\W{default}') _Title("log", "[GDB Log @\\W{number}]\\W{default}")
_Title('stack', '[GDB Stack @\\W{number}]') _Title("stack", "[GDB Stack @\\W{number}]")
warn_missing = _Missing() warn_missing = _Missing()
line_numbers = _Lines() line_numbers = _Lines()

View File

@@ -31,6 +31,7 @@ import gui.bpcache
from gi.repository import Gtk, GtkSource, GObject, Gdk, GdkPixbuf, Pango from gi.repository import Gtk, GtkSource, GObject, Gdk, GdkPixbuf, Pango
class BufferManager: class BufferManager:
def __init__(self): def __init__(self):
self.buffers = {} self.buffers = {}
@@ -38,7 +39,7 @@ class BufferManager:
gui.params.source_theme.set_buffer_manager(self) gui.params.source_theme.set_buffer_manager(self)
gui.events.location_changed.connect(self._location_changed) gui.events.location_changed.connect(self._location_changed)
# FIXME - emit a warning if this isn't available. # FIXME - emit a warning if this isn't available.
if hasattr(gdb.events, 'clear_objfiles'): if hasattr(gdb.events, "clear_objfiles"):
gdb.events.clear_objfiles.connect(self._clear_objfiles) gdb.events.clear_objfiles.connect(self._clear_objfiles)
self.empty_buffer = None self.empty_buffer = None
@@ -60,13 +61,13 @@ class BufferManager:
while True: while True:
line = iter.get_line() + 1 line = iter.get_line() + 1
if line in line_set: if line in line_set:
buffer.create_source_mark(None, 'executable', iter) buffer.create_source_mark(None, "executable", iter)
if not iter.forward_line(): if not iter.forward_line():
break break
@in_gdb_thread @in_gdb_thread
def _get_lines_update(self, buffer, symtab): def _get_lines_update(self, buffer, symtab):
if hasattr(symtab, 'linetable'): if hasattr(symtab, "linetable"):
line_set = set(symtab.linetable().source_lines()) line_set = set(symtab.linetable().source_lines())
gui.startup.send_to_gtk(lambda: self._set_marks(buffer, line_set)) gui.startup.send_to_gtk(lambda: self._set_marks(buffer, line_set))
@@ -113,9 +114,9 @@ class BufferManager:
@in_gtk_thread @in_gtk_thread
def update_breakpoint_location(self, sal, is_set): def update_breakpoint_location(self, sal, is_set):
if is_set: if is_set:
category = 'breakpoint' category = "breakpoint"
else: else:
category = 'executable' category = "executable"
[fullname, line] = sal [fullname, line] = sal
if fullname in self.buffers: if fullname in self.buffers:
buffer = self.buffers[fullname] buffer = self.buffers[fullname]
@@ -125,8 +126,7 @@ class BufferManager:
@in_gdb_thread @in_gdb_thread
def _location_changed(self, loc, is_set): def _location_changed(self, loc, is_set):
gui.startup.send_to_gtk(lambda: self.update_breakpoint_location(loc, gui.startup.send_to_gtk(lambda: self.update_breakpoint_location(loc, is_set))
is_set))
@in_gtk_thread @in_gtk_thread
def _gtk_clear_objfiles(self): def _gtk_clear_objfiles(self):
@@ -144,9 +144,10 @@ class BufferManager:
for key in self.buffers: for key in self.buffers:
buff = self.buffers[key] buff = self.buffers[key]
# This could probably be more efficient. # This could probably be more efficient.
buff.remove_source_marks(buff.get_start_iter(), buff.remove_source_marks(
buff.get_end_iter(), buff.get_start_iter(), buff.get_end_iter(), "pointer"
'pointer') )
buffer_manager = BufferManager() buffer_manager = BufferManager()
@@ -168,7 +169,7 @@ def get_current_location():
# No frame - try 'main'. # No frame - try 'main'.
try: try:
frame = None frame = None
sym = gdb.lookup_global_symbol('main') sym = gdb.lookup_global_symbol("main")
lineno = sym.line lineno = sym.line
symtab = sym.symtab symtab = sym.symtab
filename = symtab.fullname() filename = symtab.fullname()
@@ -179,6 +180,7 @@ def get_current_location():
return (None, None, None, None) return (None, None, None, None)
return (frame, symtab, filename, lineno) return (frame, symtab, filename, lineno)
class LRUHandler: class LRUHandler:
def __init__(self): def __init__(self):
self.windows = [] self.windows = []
@@ -190,10 +192,9 @@ class LRUHandler:
if len(self.windows) == 0: if len(self.windows) == 0:
self.work_location = (frame, symtab, srcfile, srcline) self.work_location = (frame, symtab, srcfile, srcline)
SourceWindow() SourceWindow()
gui.startup.send_to_gtk(lambda: self.show_source(frame, gui.startup.send_to_gtk(
symtab, lambda: self.show_source(frame, symtab, srcfile, srcline)
srcfile, )
srcline))
@in_gdb_thread @in_gdb_thread
def new_source_window(self): def new_source_window(self):
@@ -204,16 +205,15 @@ class LRUHandler:
def on_event(self, *args): def on_event(self, *args):
(frame, symtab, filename, lineno) = get_current_location() (frame, symtab, filename, lineno) = get_current_location()
if filename is not None: if filename is not None:
gui.startup.send_to_gtk(lambda: self.show_source(frame, gui.startup.send_to_gtk(
symtab, lambda: self.show_source(frame, symtab, filename, lineno)
filename, )
lineno))
@in_gdb_thread @in_gdb_thread
def _connect_events(self): def _connect_events(self):
gdb.events.stop.connect(self.on_event) gdb.events.stop.connect(self.on_event)
gui.events.frame_changed.connect(self.on_event) gui.events.frame_changed.connect(self.on_event)
if hasattr(gdb.events, 'new_objfile'): if hasattr(gdb.events, "new_objfile"):
gdb.events.new_objfile.connect(self._new_objfile) gdb.events.new_objfile.connect(self._new_objfile)
@in_gdb_thread @in_gdb_thread
@@ -263,27 +263,28 @@ class LRUHandler:
if self.work_location is not None: if self.work_location is not None:
(frame, symtab, filename, lineno) = self.work_location (frame, symtab, filename, lineno) = self.work_location
self.work_location = None self.work_location = None
gui.startup.send_to_gtk(lambda: self.show_source(frame, gui.startup.send_to_gtk(
symtab, lambda: self.show_source(frame, symtab, filename, lineno)
filename, )
lineno))
@in_gdb_thread @in_gdb_thread
def _new_objfile(self, event): def _new_objfile(self, event):
if len(gdb.objfiles()) == 1: if len(gdb.objfiles()) == 1:
self.on_event() self.on_event()
lru_handler = LRUHandler() lru_handler = LRUHandler()
BUTTON_NAMES = ["step", "next", "continue", "finish", "stop", "up", "down"] BUTTON_NAMES = ["step", "next", "continue", "finish", "stop", "up", "down"]
class SourceWindow(gui.updatewindow.UpdateWindow): class SourceWindow(gui.updatewindow.UpdateWindow):
def _get_pixmap(self, filename): def _get_pixmap(self, filename):
path = os.path.join(gui.self_dir, filename) path = os.path.join(gui.self_dir, filename)
return GdkPixbuf.Pixbuf.new_from_file(path) return GdkPixbuf.Pixbuf.new_from_file(path)
def __init__(self): def __init__(self):
super(SourceWindow, self).__init__('source') super(SourceWindow, self).__init__("source")
gdb.events.cont.connect(self._on_cont_event) gdb.events.cont.connect(self._on_cont_event)
# Update the buttons. # Update the buttons.
self.on_event() self.on_event()
@@ -300,7 +301,7 @@ class SourceWindow(gui.updatewindow.UpdateWindow):
self.do_up = FrameCommandInvoker("up") self.do_up = FrameCommandInvoker("up")
self.do_down = FrameCommandInvoker("down") self.do_down = FrameCommandInvoker("down")
builder = gui.startup.create_builder('sourcewindow.xml') builder = gui.startup.create_builder("sourcewindow.xml")
builder.connect_signals(self) builder.connect_signals(self)
self.window = builder.get_object("sourcewindow") self.window = builder.get_object("sourcewindow")
self.view = builder.get_object("view") self.view = builder.get_object("view")
@@ -315,16 +316,16 @@ class SourceWindow(gui.updatewindow.UpdateWindow):
self.view.set_tab_width(gui.params.tab_width.value) self.view.set_tab_width(gui.params.tab_width.value)
attrs = GtkSource.MarkAttributes() attrs = GtkSource.MarkAttributes()
attrs.set_pixbuf(self._get_pixmap('icons/ok.png')) attrs.set_pixbuf(self._get_pixmap("icons/ok.png"))
self.view.set_mark_attributes('executable', attrs, 0) self.view.set_mark_attributes("executable", attrs, 0)
attrs = GtkSource.MarkAttributes() attrs = GtkSource.MarkAttributes()
attrs.set_pixbuf(self._get_pixmap('icons/breakpoint-marker.png')) attrs.set_pixbuf(self._get_pixmap("icons/breakpoint-marker.png"))
self.view.set_mark_attributes('breakpoint', attrs, 1) self.view.set_mark_attributes("breakpoint", attrs, 1)
attrs = GtkSource.MarkAttributes() attrs = GtkSource.MarkAttributes()
attrs.set_pixbuf(self._get_pixmap('icons/line-pointer.png')) attrs.set_pixbuf(self._get_pixmap("icons/line-pointer.png"))
self.view.set_mark_attributes('pointer', attrs, 2) self.view.set_mark_attributes("pointer", attrs, 2)
self.view.set_buffer(buffer_manager.get_empty_buffer()) self.view.set_buffer(buffer_manager.get_empty_buffer())
lru_handler.add(self) lru_handler.add(self)
@@ -370,7 +371,7 @@ class SourceWindow(gui.updatewindow.UpdateWindow):
def _do_scroll(self, buff, srcline): def _do_scroll(self, buff, srcline):
iter = buff.get_iter_at_line(srcline) iter = buff.get_iter_at_line(srcline)
buff.create_source_mark(None, 'pointer', iter) buff.create_source_mark(None, "pointer", iter)
buff.place_cursor(iter) buff.place_cursor(iter)
self.view.scroll_mark_onscreen(buff.get_insert()) self.view.scroll_mark_onscreen(buff.get_insert())
return False return False

View File

@@ -27,6 +27,7 @@ from gui.framecache import FrameCommandInvoker
from gui.startup import in_gdb_thread, in_gtk_thread from gui.startup import in_gdb_thread, in_gtk_thread
from gi.repository import Gtk from gi.repository import Gtk
def format_frame(frame): def format_frame(frame):
result = {} result = {}
result["name"] = frame.function() result["name"] = frame.function()
@@ -42,10 +43,11 @@ def format_frame(frame):
return result return result
# FIXME args # FIXME args
class StackWindow(gui.updatewindow.UpdateWindow): class StackWindow(gui.updatewindow.UpdateWindow):
def __init__(self): def __init__(self):
self.raw = False self.raw = False
super(StackWindow, self).__init__('stack') super(StackWindow, self).__init__("stack")
# Connect events. # Connect events.
# Update buttons. # Update buttons.
@@ -53,11 +55,11 @@ class StackWindow(gui.updatewindow.UpdateWindow):
def gtk_initialize(self): def gtk_initialize(self):
self.do_up = FrameCommandInvoker("up") self.do_up = FrameCommandInvoker("up")
self.do_down = FrameCommandInvoker("down") self.do_down = FrameCommandInvoker("down")
builder = gui.startup.create_builder('stackwindow.xml') builder = gui.startup.create_builder("stackwindow.xml")
builder.connect_signals(self) builder.connect_signals(self)
self.window = builder.get_object('stackwindow') self.window = builder.get_object("stackwindow")
self.view = builder.get_object('view') self.view = builder.get_object("view")
self.text = Gtk.TextBuffer() self.text = Gtk.TextBuffer()
self.view.set_buffer(self.text) self.view.set_buffer(self.text)
self.view.modify_font(gui.params.font_manager.get_font()) self.view.modify_font(gui.params.font_manager.get_font())
@@ -67,7 +69,7 @@ class StackWindow(gui.updatewindow.UpdateWindow):
self.text.delete(self.text.get_start_iter(), self.text.get_end_iter()) self.text.delete(self.text.get_start_iter(), self.text.get_end_iter())
frame_no = 1 frame_no = 1
for frame in data: for frame in data:
self.text.insert_at_cursor('#%d ' % frame_no) self.text.insert_at_cursor("#%d " % frame_no)
frame_no = frame_no + 1 frame_no = frame_no + 1
# Goofball API. # Goofball API.
if isinstance(frame["name"], str): if isinstance(frame["name"], str):
@@ -80,8 +82,9 @@ class StackWindow(gui.updatewindow.UpdateWindow):
# FIXME args # FIXME args
self.text.insert_at_cursor("\n") self.text.insert_at_cursor("\n")
if frame["line"] is not None: if frame["line"] is not None:
self.text.insert_at_cursor(" at %s:%d\n" % (frame["filename"], self.text.insert_at_cursor(
frame["line"])) " at %s:%d\n" % (frame["filename"], frame["line"])
)
if frame["solib"] is not None: if frame["solib"] is not None:
self.text.insert_at_cursor(" [%s]\n" % frame["solib"]) self.text.insert_at_cursor(" [%s]\n" % frame["solib"])
@@ -91,11 +94,12 @@ class StackWindow(gui.updatewindow.UpdateWindow):
try: try:
start_frame = gdb.newest_frame() start_frame = gdb.newest_frame()
if not self.raw: if not self.raw:
frame_iter = gdb.frames.execute_frame_filters(start_frame, frame_iter = gdb.frames.execute_frame_filters(start_frame, 0, -1)
0, -1)
if frame_iter is None: if frame_iter is None:
frame_iter = map(gdb.FrameDecorator.FrameDecorator, frame_iter = map(
gdb.FrameIterator.FrameIterator(start_frame)) gdb.FrameDecorator.FrameDecorator,
gdb.FrameIterator.FrameIterator(start_frame),
)
data = list(map(format_frame, frame_iter)) data = list(map(format_frame, frame_iter))
except gdb.error: except gdb.error:
data = [] data = []
@@ -105,6 +109,7 @@ class StackWindow(gui.updatewindow.UpdateWindow):
def set_font(self, pango_font): def set_font(self, pango_font):
self.view.modify_font(pango_font) self.view.modify_font(pango_font)
def show_stack(): def show_stack():
# for now # for now
StackWindow() StackWindow()

View File

@@ -22,9 +22,9 @@ import gui
import gi import gi
gi.require_version('Gtk', '3.0') gi.require_version("Gtk", "3.0")
gi.require_version('GtkSource', '3.0') gi.require_version("GtkSource", "3.0")
gi.require_version('Notify', '0.7') gi.require_version("Notify", "0.7")
from gi.repository import Gtk, Gdk, GObject, GtkSource, GLib, GdkPixbuf from gi.repository import Gtk, Gdk, GObject, GtkSource, GLib, GdkPixbuf
@@ -32,11 +32,13 @@ from gi.repository import Gtk, Gdk, GObject, GtkSource, GLib, GdkPixbuf
_event_queue = queue.Queue() _event_queue = queue.Queue()
def send_to_gtk(func): def send_to_gtk(func):
_event_queue.put(func) _event_queue.put(func)
# The payload is arbitrary. # The payload is arbitrary.
os.write(write_pipe, bytes(1)) os.write(write_pipe, bytes(1))
class _GtkThread(gdb.Thread): class _GtkThread(gdb.Thread):
def handle_queue(self, source, condition): def handle_queue(self, source, condition):
global _event_queue global _event_queue
@@ -51,17 +53,19 @@ class _GtkThread(gdb.Thread):
GObject.type_register(GtkSource.View) GObject.type_register(GtkSource.View)
Gtk.main() Gtk.main()
_gdb_thread = threading.current_thread() _gdb_thread = threading.current_thread()
_t = None _t = None
def start_gtk(): def start_gtk():
global _t global _t
if _t is None: if _t is None:
GLib.set_application_name('GDB') GLib.set_application_name("GDB")
GLib.set_prgname('GDB') GLib.set_prgname("GDB")
Gdk.set_program_class('GDB') Gdk.set_program_class("GDB")
Gtk.Window.set_default_icon_name('GDB') Gtk.Window.set_default_icon_name("GDB")
path = os.path.join(gui.self_dir, 'icons/face-raspberry-symbolic.svg') path = os.path.join(gui.self_dir, "icons/face-raspberry-symbolic.svg")
Gtk.Window.set_default_icon(GdkPixbuf.Pixbuf.new_from_file(path)) Gtk.Window.set_default_icon(GdkPixbuf.Pixbuf.new_from_file(path))
GObject.threads_init() GObject.threads_init()
Gdk.threads_init() Gdk.threads_init()
@@ -69,21 +73,26 @@ def start_gtk():
_t.setDaemon(True) _t.setDaemon(True)
_t.start() _t.start()
def create_builder(filename): def create_builder(filename):
builder = Gtk.Builder() builder = Gtk.Builder()
builder.add_from_file(os.path.join(gui.self_dir, filename)) builder.add_from_file(os.path.join(gui.self_dir, filename))
return builder return builder
def in_gdb_thread(func): def in_gdb_thread(func):
def ensure_gdb_thread(*args, **kwargs): def ensure_gdb_thread(*args, **kwargs):
if threading.current_thread() is not _gdb_thread: if threading.current_thread() is not _gdb_thread:
raise RuntimeError("must run '%s' in gdb thread" % repr(func)) raise RuntimeError("must run '%s' in gdb thread" % repr(func))
return func(*args, **kwargs) return func(*args, **kwargs)
return ensure_gdb_thread return ensure_gdb_thread
def in_gtk_thread(func): def in_gtk_thread(func):
def ensure_gtk_thread(*args, **kwargs): def ensure_gtk_thread(*args, **kwargs):
if threading.current_thread() is not _t: if threading.current_thread() is not _t:
raise RuntimeError("must run '%s' in Gtk thread" % repr(func)) raise RuntimeError("must run '%s' in Gtk thread" % repr(func))
return func(*args, **kwargs) return func(*args, **kwargs)
return ensure_gtk_thread return ensure_gtk_thread

View File

@@ -21,10 +21,11 @@ import errno
import configparser import configparser
import atexit import atexit
class StorageManager: class StorageManager:
def __init__(self): def __init__(self):
self.dir = os.path.join(GLib.get_user_config_dir(), 'gdb') self.dir = os.path.join(GLib.get_user_config_dir(), "gdb")
self.file = os.path.join(self.dir, 'settings') self.file = os.path.join(self.dir, "settings")
try: try:
os.mkdir(self.dir, 0o700) os.mkdir(self.dir, 0o700)
except OSError as exc: except OSError as exc:
@@ -33,30 +34,31 @@ class StorageManager:
self.config = configparser.RawConfigParser() self.config = configparser.RawConfigParser()
if self.file is not None: if self.file is not None:
self.config.read(self.file) self.config.read(self.file)
if not self.config.has_section('general'): if not self.config.has_section("general"):
self.config.add_section('general') self.config.add_section("general")
atexit.register(self.write) atexit.register(self.write)
def get(self, name): def get(self, name):
if self.config.has_option('general', name): if self.config.has_option("general", name):
return self.config.get('general', name) return self.config.get("general", name)
return None return None
def getboolean(self, name): def getboolean(self, name):
if self.config.has_option('general', name): if self.config.has_option("general", name):
return self.config.getboolean('general', name) return self.config.getboolean("general", name)
return None return None
def getint(self, name): def getint(self, name):
if self.config.has_option('general', name): if self.config.has_option("general", name):
return self.config.getint('general', name) return self.config.getint("general", name)
return None return None
def set(self, name, value): def set(self, name, value):
self.config.set('general', name, value) self.config.set("general", name, value)
def write(self): def write(self):
with open(self.file, 'wt') as save_file: with open(self.file, "wt") as save_file:
self.config.write(save_file) self.config.write(save_file)
storage_manager = StorageManager() storage_manager = StorageManager()

View File

@@ -25,6 +25,7 @@ import threading
from gi.repository import Pango from gi.repository import Pango
from gui.startup import in_gdb_thread, in_gtk_thread from gui.startup import in_gdb_thread, in_gtk_thread
class _ToplevelState(object): class _ToplevelState(object):
def __init__(self): def __init__(self):
gui.startup.start_gtk() gui.startup.start_gtk()
@@ -73,12 +74,11 @@ class _ToplevelState(object):
print("No windows") print("No windows")
return return
print(' Num Name') print(" Num Name")
for winno in range(1, self.next_toplevel): for winno in range(1, self.next_toplevel):
if winno in self.toplevels: if winno in self.toplevels:
window = self.toplevels[winno] window = self.toplevels[winno]
print(' %3d %s' % (window.number, print(" %3d %s" % (window.number, window.window.get_title()))
window.window.get_title()))
@in_gtk_thread @in_gtk_thread
def _do_set_font(self, font_name): def _do_set_font(self, font_name):
@@ -125,15 +125,17 @@ class _ToplevelState(object):
def windows(self): def windows(self):
return list(self.toplevels.values()) return list(self.toplevels.values())
state = _ToplevelState() state = _ToplevelState()
class Toplevel(object): class Toplevel(object):
def __init__(self, window_type): def __init__(self, window_type):
state.add(self, window_type) state.add(self, window_type)
# The subclass must set this. # The subclass must set this.
self.window = None self.window = None
self.window_type = window_type self.window_type = window_type
self.storage_name = window_type + '-' + str(self.type_number) + '-geom' self.storage_name = window_type + "-" + str(self.type_number) + "-geom"
gui.startup.send_to_gtk(self._do_gtk_initialize) gui.startup.send_to_gtk(self._do_gtk_initialize)
@in_gtk_thread @in_gtk_thread
@@ -145,7 +147,7 @@ class Toplevel(object):
@in_gtk_thread @in_gtk_thread
def _do_gtk_initialize(self): def _do_gtk_initialize(self):
self.gtk_initialize() self.gtk_initialize()
self.window.connect('configure-event', self._on_resize) self.window.connect("configure-event", self._on_resize)
geom = gui.storage.storage_manager.get(self.storage_name) geom = gui.storage.storage_manager.get(self.storage_name)
if geom: if geom:
self.window.parse_geometry(geom) self.window.parse_geometry(geom)
@@ -158,7 +160,7 @@ class Toplevel(object):
@in_gtk_thread @in_gtk_thread
def _on_resize(self, widget, event): def _on_resize(self, widget, event):
geom = '%dx%d+%d+%d' % (event.width, event.height, event.x, event.y) geom = "%dx%d+%d+%d" % (event.width, event.height, event.x, event.y)
gdb.post_event(lambda: self._save_size(geom)) gdb.post_event(lambda: self._save_size(geom))
return False return False

View File

@@ -21,6 +21,7 @@ from gui.startup import in_gdb_thread, in_gtk_thread
import gdb import gdb
import gui.events import gui.events
class UpdateWindow(Toplevel): class UpdateWindow(Toplevel):
"""A window that automatically updates in response to gdb changes. """A window that automatically updates in response to gdb changes.

5
pyproject.toml Normal file
View File

@@ -0,0 +1,5 @@
[tool.black]
include = "\\.py(\\.in)?$"
[tool.pyright]
typeCheckingMode = "strict"