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
sys.path.append('HERE')
sys.path.append("HERE")
import gui.commands

View File

@@ -24,18 +24,15 @@ bugs = {
15620: """Your gdb doesn't have a "new breakpoint" event.
This means that the source windows will not show you where
breakpoints have been set.""",
13598: """Your gdb doesn't have a "before prompt" event.
This means that various windows won't be able to react to
commands like "up" or "down".""",
18385: """Your gdb doesn't expose locations on a gdb.Breakpoint.
This can be worked around, but maybe not always reliably.
This means that sometimes breakpoints won't display in source windows.""",
18620: """Your gdb doesn't have a "breakpoint modified" event.
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
@@ -43,6 +40,7 @@ for more information."""
_first_report = True
def notify_bug(bugno):
if not gui.params.warn_missing.value:
return

View File

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

View File

@@ -27,33 +27,33 @@ import gui.adapt
import re
from gui.startup import in_gtk_thread
class GuiCommand(gdb.Command):
def __init__(self):
super(GuiCommand, self).__init__('gui', gdb.COMMAND_SUPPORT,
prefix = True)
super(GuiCommand, self).__init__("gui", gdb.COMMAND_SUPPORT, prefix=True)
class GuiSourceCommand(gdb.Command):
"""Create a new source window.
Usage: gui source
This creates a new source window in the GUI. Any number of source
windows can be created."""
Usage: gui source
This creates a new source window in the GUI. Any number of source
windows can be created."""
def __init__(self):
super(GuiSourceCommand, self).__init__('gui source',
gdb.COMMAND_SUPPORT)
super(GuiSourceCommand, self).__init__("gui source", gdb.COMMAND_SUPPORT)
def invoke(self, arg, from_tty):
self.dont_repeat()
gui.source.lru_handler.new_source_window()
class GuiStackCommand(gdb.Command):
"""Create a new stack window.
Usage: gui stack
This creates a stack window in the GUI if it does not already exist."""
Usage: gui stack
This creates a stack window in the GUI if it does not already exist."""
def __init__(self):
super(GuiStackCommand, self).__init__('gui stack',
gdb.COMMAND_SUPPORT)
super(GuiStackCommand, self).__init__("gui stack", gdb.COMMAND_SUPPORT)
def invoke(self, arg, from_tty):
self.dont_repeat()
@@ -64,45 +64,45 @@ This creates a stack window in the GUI if it does not already exist."""
# or maybe even whatever 'bt' takes?
gui.stack.show_stack()
class GuiListCommand(gdb.Command):
"""List some source code in a source window.
Usage: gui list LINESPEC
This command uses LINESPEC to show some source code in a source
window. If a source window is already available, the source is
displayed there. Otherwise, a new source window is made.
LINESPEC is a line specification of the form given to 'break'."""
Usage: gui list LINESPEC
This command uses LINESPEC to show some source code in a source
window. If a source window is already available, the source is
displayed there. Otherwise, a new source window is made.
LINESPEC is a line specification of the form given to 'break'."""
def __init__(self):
super(GuiListCommand, self).__init__('gui list',
gdb.COMMAND_SUPPORT)
super(GuiListCommand, self).__init__("gui list", gdb.COMMAND_SUPPORT)
def invoke(self, arg, from_tty):
self.dont_repeat()
(extra, sals) = gdb.decode_line(arg)
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:
raise gdb.GdbError('not found')
raise gdb.GdbError("not found")
if len(sals) > 1:
print("Ambiguous linespec, only showing first result")
sal = sals[0]
if sal.symtab is None or sal.symtab.filename is None:
raise gdb.GdbError('could not find file for symbol')
gui.source.lru_handler.show_source_gdb(None, sal.symtab,
sal.symtab.fullname(),
sal.line)
raise gdb.GdbError("could not find file for symbol")
gui.source.lru_handler.show_source_gdb(
None, sal.symtab, sal.symtab.fullname(), sal.line
)
class GuiShowCommand(gdb.Command):
"""Show the source for a symbol in a source window.
Usage: gui show SYMBOL
This command looks for the definition of SYMBOL in the program and
shows its source location in a source window. If a source window is
already available, the source is displayed there. Otherwise, a new
source window is made."""
Usage: gui show SYMBOL
This command looks for the definition of SYMBOL in the program and
shows its source location in a source window. If a source window is
already available, the source is displayed there. Otherwise, a new
source window is made."""
def __init__(self):
super(GuiShowCommand, self).__init__('gui show',
gdb.COMMAND_SUPPORT)
super(GuiShowCommand, self).__init__("gui show", gdb.COMMAND_SUPPORT)
def invoke(self, arg, from_tty):
self.dont_repeat()
@@ -113,101 +113,110 @@ source window is made."""
raise
symbol = gdb.lookup_global_symbol(arg)
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:
raise gdb.GdbError('symbol ' + arg
+ ' does not seem to have an associated file')
gui.source.lru_handler.show_source_gdb(None, symbol.symtab,
symbol.symtab.fullname(),
symbol.line)
raise gdb.GdbError(
"symbol " + arg + " does not seem to have an associated file"
)
gui.source.lru_handler.show_source_gdb(
None, symbol.symtab, symbol.symtab.fullname(), symbol.line
)
class GuiLogWindowCommand(gdb.Command):
"""Create a new log window.
Usage: gui log
This creates a new "log" window in the GUI. A log window is used
to display output from "gui print", "gui printf", "gui output",
and "gui dprintf".
Usage: gui log
This creates a new "log" window in the GUI. A log window is used
to display output from "gui print", "gui printf", "gui output",
and "gui dprintf".
Multiple log windows can be created and output can be directed to
a given instance using the "@" syntax, like:
Multiple log windows can be created and output can be directed to
a given instance using the "@" syntax, like:
gui print @5 variable"""
gui print @5 variable"""
def __init__(self):
super(GuiLogWindowCommand, self).__init__('gui log',
gdb.COMMAND_SUPPORT)
super(GuiLogWindowCommand, self).__init__("gui log", gdb.COMMAND_SUPPORT)
def invoke(self, arg, from_tty):
self.dont_repeat()
window = gui.logwindow.LogWindow()
print("Created log window %d; now the default" % window.number)
class GuiPrintBase(gdb.Command):
def __init__(self, command):
super(GuiPrintBase, self).__init__('gui ' + command,
gdb.COMMAND_SUPPORT)
super(GuiPrintBase, self).__init__("gui " + command, gdb.COMMAND_SUPPORT)
self.command = command
# 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()
match = re.match('@(\\d+)\\s+(.*)$', arg)
match = re.match("@(\\d+)\\s+(.*)$", arg)
if match is not None:
winno = int(match.group(1))
arg = match.group(2)
window = gui.toplevel.state.get(winno)
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):
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:
window = gui.logwindow.default_log_window
if window is None:
raise gdb.GdbError('no default log window')
raise gdb.GdbError("no default log window")
else:
window = None
return (window, arg)
def invoke(self, arg, from_tty):
(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)
class GuiPrintCommand(GuiPrintBase):
"""Print to a gui log window.
Usage: gui print [@N] ARGS
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
window; otherwise, output goes to the most recently created log window."""
Usage: gui print [@N] ARGS
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
window; otherwise, output goes to the most recently created log window."""
def __init__(self):
super(GuiPrintCommand, self).__init__('print')
super(GuiPrintCommand, self).__init__("print")
class GuiOutputCommand(GuiPrintBase):
"""Output to a gui log window.
Usage: gui output [@N] ARGS
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
window; otherwise, output goes to the most recently created log window."""
Usage: gui output [@N] ARGS
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
window; otherwise, output goes to the most recently created log window."""
def __init__(self):
super(GuiOutputCommand, self).__init__('output')
super(GuiOutputCommand, self).__init__("output")
class GuiPrintfCommand(GuiPrintBase):
"""printf to a gui log window.
Usage: gui printf [@N] ARGS
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
window; otherwise, output goes to the most recently created log window."""
Usage: gui printf [@N] ARGS
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
window; otherwise, output goes to the most recently created log window."""
def __init__(self):
super(GuiPrintfCommand, self).__init__('printf')
super(GuiPrintfCommand, self).__init__("printf")
class GuiDprintfCommand(GuiPrintBase):
"""dprintf to a gui log window.
Usage: gui dprintf [@N] ARGS
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
window; otherwise, output goes to the most recently created log window."""
Usage: gui dprintf [@N] ARGS
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
window; otherwise, output goes to the most recently created log window."""
def __init__(self):
super(GuiDprintfCommand, self).__init__('dprintf')
super(GuiDprintfCommand, self).__init__("dprintf")
def invoke(self, arg, from_tty):
(window, arg) = self._parse_arg(arg, False)
@@ -216,29 +225,29 @@ window; otherwise, output goes to the most recently created log window."""
if arg is None:
raise gdb.GdbError("no printf arguments to 'gui dprintf'")
arg = arg.strip()
if not arg.startswith(','):
if not arg.startswith(","):
raise gdb.GdbError("comma expected after linespec")
arg = arg[1:]
spec = arg[0 : -len(arg)]
DPrintfBreakpoint(spec, window, arg)
class GuiDisplayCommand(gdb.Command):
"""Create a new display window.
Usage: gui display [-diff] COMMAND
Usage: gui display [-diff] COMMAND
A display window runs a gdb command after operations that change the
current frame or that cause the inferior to stop. If "-diff" is
given, then every time the display is updated, changed lines are
highlighted."""
A display window runs a gdb command after operations that change the
current frame or that cause the inferior to stop. If "-diff" is
given, then every time the display is updated, changed lines are
highlighted."""
def __init__(self):
super(GuiDisplayCommand, self).__init__('gui display',
gdb.COMMAND_SUPPORT)
super(GuiDisplayCommand, self).__init__("gui display", gdb.COMMAND_SUPPORT)
def invoke(self, arg, from_tty):
self.dont_repeat()
diff = False
if arg.startswith('-diff '):
if arg.startswith("-diff "):
diff = True
arg = arg[6:]
gui.display.DisplayWindow(arg, diff)
@@ -248,31 +257,31 @@ highlighted."""
# https://sourceware.org/bugzilla/show_bug.cgi?id=13077
return None
class InfoWindowsCommand(gdb.Command):
"""List all the GUI windows.
Usage: info windows
This lists all the GUI windows.
Note that this should not be confused with "info win", which is
part of the TUI."""
Usage: info windows
This lists all the GUI windows.
Note that this should not be confused with "info win", which is
part of the TUI."""
def __init__(self):
super(InfoWindowsCommand, self).__init__('info windows',
gdb.COMMAND_SUPPORT)
super(InfoWindowsCommand, self).__init__("info windows", gdb.COMMAND_SUPPORT)
def invoke(self, arg, from_tty):
self.dont_repeat()
gui.toplevel.state.display()
class DeleteWindowsCommand(gdb.Command):
"""Delete a GUI window.
Usage: delete window N
Delete GUI window number N.
A window's number appears in its title bar, and can also be
found using "info windows"."""
Usage: delete window N
Delete GUI window number N.
A window's number appears in its title bar, and can also be
found using "info windows"."""
def __init__(self):
super(DeleteWindowsCommand, self).__init__('delete window',
gdb.COMMAND_SUPPORT)
super(DeleteWindowsCommand, self).__init__("delete window", gdb.COMMAND_SUPPORT)
def invoke(self, arg, from_tty):
self.dont_repeat()
@@ -281,6 +290,7 @@ found using "info windows"."""
if window is not None:
window.destroy()
GuiCommand()
GuiSourceCommand()
GuiStackCommand()
@@ -304,7 +314,7 @@ class TestCommand(gdb.Command):
your copy of gdb has some command-overriding support."""
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
def invoke(self, arg, from_tty):
@@ -317,13 +327,15 @@ class TestCommand(gdb.Command):
except:
pass
TestCommand(True)
TestCommand(False).invoke('', 0)
TestCommand(False).invoke("", 0)
# See framecache.py - we prefer the before_prompt event if it exists;
# but otherwise try the overriding approach. Both of these rely on a
# 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):
def __init__(self, name, event):
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)
self.event.post()
Overrider('up', gui.events.frame_changed)
Overrider('down', gui.events.frame_changed)
Overrider('frame', gui.events.frame_changed)
Overrider("up", gui.events.frame_changed)
Overrider("down", gui.events.frame_changed)
Overrider("frame", gui.events.frame_changed)

View File

@@ -27,38 +27,38 @@ from difflib import SequenceMatcher, Differ
# FIXME: TO DO:
# * highlight the changes
class DisplayWindow(gui.updatewindow.UpdateWindow):
def __init__(self, command, diff = False):
def __init__(self, command, diff=False):
self.command = command
self.diff = diff
self.last_text = None
super(DisplayWindow, self).__init__('display')
super(DisplayWindow, self).__init__("display")
@in_gdb_thread
def on_event(self):
try:
text = gdb.execute(self.command, to_string = True)
text = gdb.execute(self.command, to_string=True)
except gdb.error as what:
text = str(what)
gui.startup.send_to_gtk(lambda: self._update(text))
@in_gtk_thread
def gtk_initialize(self):
builder = gui.startup.create_builder('logwindow.xml')
builder = gui.startup.create_builder("logwindow.xml")
builder.connect_signals(self)
self.window = builder.get_object('logwindow')
self.view = builder.get_object('textview')
self.view.modify_font(Pango.FontDescription('Fixed'))
self.window = builder.get_object("logwindow")
self.view = builder.get_object("textview")
self.view.modify_font(Pango.FontDescription("Fixed"))
self.buffer = builder.get_object('buffer')
self.buffer = builder.get_object("buffer")
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):
self.buffer.delete(self.buffer.get_start_iter(),
self.buffer.get_end_iter())
self.buffer.delete(self.buffer.get_start_iter(), self.buffer.get_end_iter())
if self.diff:
if self.last_text is None:
self.last_text = text.splitlines(1)
@@ -67,14 +67,13 @@ class DisplayWindow(gui.updatewindow.UpdateWindow):
split = text.splitlines(1)
d = Differ()
for line in d.compare(self.last_text, split):
if line[0] == ' ':
self.buffer.insert(self.buffer.get_end_iter(),
line[2:])
elif line[0] == '+':
self.buffer.insert_with_tags(self.buffer.get_end_iter(),
line[2:],
self.tag)
self.buffer.insert(self.buffer.get_end_iter(), '\n')
if line[0] == " ":
self.buffer.insert(self.buffer.get_end_iter(), line[2:])
elif line[0] == "+":
self.buffer.insert_with_tags(
self.buffer.get_end_iter(), line[2:], self.tag
)
self.buffer.insert(self.buffer.get_end_iter(), "\n")
self.last_text = split
return
self.buffer.insert_at_cursor(text)

View File

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

View File

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

View File

@@ -22,6 +22,7 @@ from gui.startup import in_gdb_thread
_last_selected_frame = None
def check_frame():
global _last_selected_frame
sel = None
@@ -33,6 +34,7 @@ def check_frame():
_last_selected_frame = sel
gui.events.frame_changed.post()
# 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.
class FrameCommandInvoker(gui.invoker.Invoker):
@@ -41,8 +43,9 @@ class FrameCommandInvoker(gui.invoker.Invoker):
gui.invoker.Invoker.do_call(self)
check_frame()
# 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)
else:
gui.adapt.notify_bug(13598)

View File

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

View File

@@ -16,6 +16,7 @@
import gdb
from gui.startup import in_gdb_thread
class Invoker(object):
"""A simple class that can invoke a gdb command.
This is suitable for use as an event handler in Gtk."""
@@ -26,7 +27,7 @@ class Invoker(object):
# This is invoked in the gdb thread to run the command.
@in_gdb_thread
def do_call(self):
gdb.execute(self.cmd, from_tty = True, to_string = True)
gdb.execute(self.cmd, from_tty=True, to_string=True)
# The object itself is the Gtk event handler -- though really this
# can be run in any thread.

View File

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

View File

@@ -27,6 +27,7 @@ _initialized = False
_last_time = None
@in_gtk_thread
def _show_notification(title, content):
global _initialized
@@ -36,41 +37,45 @@ def _show_notification(title, content):
n = Notify.Notification.new(title, content)
n.show()
@in_gdb_thread
def _on_stop(event):
global _last_time
t = _last_time
_last_time = None
if (t is None
if (
t is None
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
if isinstance(event, gdb.ExitedEvent):
title = 'gdb - inferior exited'
if hasattr(event, 'exit_code'):
content = 'inferior exited with code ' + str(event.exit_code)
title = "gdb - inferior exited"
if hasattr(event, "exit_code"):
content = "inferior exited with code " + str(event.exit_code)
else:
content = 'inferior exited, code unavailable'
content = "inferior exited, code unavailable"
elif isinstance(event, gdb.BreakpointEvent):
title = 'gdb - inferior stopped'
content = ('inferior stopped at breakpoint '
+ str(event.breakpoints[0].number))
title = "gdb - inferior stopped"
content = "inferior stopped at breakpoint " + str(event.breakpoints[0].number)
elif isinstance(event, gdb.SignalEvent):
title = 'gdb - inferior stopped'
content = 'inferior stopped with signal: ' + event.stop_signal
title = "gdb - inferior stopped"
content = "inferior stopped with signal: " + event.stop_signal
else:
title = 'gdb - inferior stopped'
content = 'inferior stopped, reason unknown'
title = "gdb - inferior stopped"
content = "inferior stopped, reason unknown"
gui.startup.send_to_gtk(lambda: _show_notification(title, content))
@in_gdb_thread
def _on_cont(event):
global _last_time
_last_time = time.process_time()
gdb.events.stop.connect(_on_stop)
gdb.events.cont.connect(_on_cont)
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 gi.repository import GtkSource, Pango
class _SetBase(gdb.Command):
"""Generic command for modifying GUI settings."""
def __init__(self):
super(_SetBase, self).__init__('set gui', gdb.COMMAND_NONE,
prefix = True)
super(_SetBase, self).__init__("set gui", gdb.COMMAND_NONE, prefix=True)
class _SetTitleBase(gdb.Command):
"""Generic command for modifying GUI window titles."""
def __init__(self):
super(_SetTitleBase, self).__init__('set gui title', gdb.COMMAND_NONE,
prefix = True)
super(_SetTitleBase, self).__init__(
"set gui title", gdb.COMMAND_NONE, prefix=True
)
class _ShowBase(gdb.Command):
"""Generic command for showing GUI settings."""
def __init__(self):
super(_ShowBase, self).__init__('show gui', gdb.COMMAND_NONE,
prefix = True)
super(_ShowBase, self).__init__("show gui", gdb.COMMAND_NONE, prefix=True)
class _ShowTitleBase(gdb.Command):
"""Generic command for showing GUI window titles."""
def __init__(self):
super(_ShowTitleBase, self).__init__('show gui title', gdb.COMMAND_NONE,
prefix = True)
super(_ShowTitleBase, self).__init__(
"show gui title", gdb.COMMAND_NONE, prefix=True
)
# Like gdb.Parameter, but has a default and automatically handles
# storage.
@@ -58,11 +63,10 @@ class _StoredParameter(gdb.Parameter):
# NAME_FORMAT is like "%s" - NAME is substituted.
# To construct the parameter name, "gui " is prefixed.
def __init__(self, name_format, name, default, c_class, p_kind, *args):
full_name = 'gui ' + name_format % name
self.storage_name = '-'.join((name_format % name).split(' '))
full_name = "gui " + name_format % name
self.storage_name = "-".join((name_format % name).split(" "))
storage = gui.storage.storage_manager
super(_StoredParameter, self).__init__(full_name, c_class, p_kind,
*args)
super(_StoredParameter, self).__init__(full_name, c_class, p_kind, *args)
if p_kind is gdb.PARAM_BOOLEAN:
val = storage.getboolean(self.storage_name)
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)
return ""
class _Theme(_StoredParameter):
# Silly gdb requirement.
""
""""""
set_doc = "Set the source window theme."
show_doc = "Show the source window theme."
def __init__(self):
self.manager = GtkSource.StyleSchemeManager.get_default()
super(_Theme, self).__init__('%s', 'theme', None,
gdb.COMMAND_NONE, gdb.PARAM_ENUM,
# Probably the wrong thread.
self.manager.get_scheme_ids())
super(_Theme, self).__init__(
"%s",
"theme",
None,
gdb.COMMAND_NONE,
gdb.PARAM_ENUM,
# Probably the wrong thread.
self.manager.get_scheme_ids(),
)
@in_gdb_thread
def set_buffer_manager(self, b):
@@ -120,17 +130,19 @@ class _Theme(_StoredParameter):
self.buffer_manager.change_theme()
return ""
class _Font(_StoredParameter):
# Silly gdb requirement.
""
""""""
set_doc = "Set the source window font."
show_doc = "Show the source window font."
def __init__(self):
self.manager = GtkSource.StyleSchemeManager.get_default()
super(_Font, self).__init__('%s', 'font', 'monospace',
gdb.COMMAND_NONE, gdb.PARAM_STRING)
super(_Font, self).__init__(
"%s", "font", "monospace", gdb.COMMAND_NONE, gdb.PARAM_STRING
)
@in_gtk_thread
def get_font(self):
@@ -147,11 +159,13 @@ class _Font(_StoredParameter):
super(_Font, self).get_set_string()
return ""
title_params = {}
class _Title(_StoredParameter):
# Silly gdb requirement.
""
""""""
def __init__(self, name, default):
title_params[name] = self
@@ -159,9 +173,10 @@ class _Title(_StoredParameter):
self.set_doc = "Set the %s window title format." % self.name
self.show_doc = "Show the %s window title format." % self.name
self.manager = GtkSource.StyleSchemeManager.get_default()
super(_Title, self).__init__('title %s', name, default,
gdb.COMMAND_NONE, gdb.PARAM_STRING)
val = self.storage.get('title-%s' % name)
super(_Title, self).__init__(
"title %s", name, default, gdb.COMMAND_NONE, gdb.PARAM_STRING
)
val = self.storage.get("title-%s" % name)
if val is not None:
self.value = val
else:
@@ -169,8 +184,7 @@ class _Title(_StoredParameter):
@in_gdb_thread
def get_show_string(self, pvalue):
return "The current title format for the %s is: %s" % (self.name,
self.value)
return "The current title format for the %s is: %s" % (self.name, self.value)
@in_gdb_thread
def get_set_string(self):
@@ -178,16 +192,18 @@ class _Title(_StoredParameter):
gui.toplevel.state.update_titles()
return ""
class _Missing(_StoredParameter):
# Silly gdb requirement.
""
""""""
set_doc = "Set whether to mention missing gdb features."
show_doc = "Show whether to mention missing gdb features."
def __init__(self):
super(_Missing, self).__init__('%s', 'mention-missing', True,
gdb.COMMAND_NONE, gdb.PARAM_BOOLEAN)
super(_Missing, self).__init__(
"%s", "mention-missing", True, gdb.COMMAND_NONE, gdb.PARAM_BOOLEAN
)
@in_gdb_thread
def get_show_string(self, pvalue):
@@ -197,21 +213,22 @@ class _Missing(_StoredParameter):
v = "off"
return "Whether to warn about missing gdb features: " + v
class _Lines(_StoredParameter):
# Silly gdb requirement.
""
""""""
set_doc = "Set whether to display line numbers in the source window."
show_doc = "Show whether to display line numbers in the source window."
def __init__(self):
super(_Lines, self).__init__('%s', 'line-numbers', False,
gdb.COMMAND_NONE, gdb.PARAM_BOOLEAN)
super(_Lines, self).__init__(
"%s", "line-numbers", False, gdb.COMMAND_NONE, gdb.PARAM_BOOLEAN
)
@in_gdb_thread
def get_show_string(self, pvalue):
return "The current title format for the %s is: %s" % (self.name,
self.value)
return "The current title format for the %s is: %s" % (self.name, self.value)
@in_gdb_thread
def get_set_string(self):
@@ -219,20 +236,24 @@ class _Lines(_StoredParameter):
gui.toplevel.state.set_line_numbers(self.value)
return ""
class _Lines(_StoredParameter):
# Silly gdb requirement.
""
""""""
set_doc = "Set whether to display line numbers in the source window."
show_doc = "Show whether to display line numbers in the source window."
def __init__(self):
super(_Lines, self).__init__('%s', 'line-numbers', False,
gdb.COMMAND_NONE, gdb.PARAM_BOOLEAN)
super(_Lines, self).__init__(
"%s", "line-numbers", False, gdb.COMMAND_NONE, gdb.PARAM_BOOLEAN
)
@in_gdb_thread
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
def get_set_string(self):
@@ -240,16 +261,18 @@ class _Lines(_StoredParameter):
gui.toplevel.state.set_line_numbers(self.value)
return ""
class _Tabs(_StoredParameter):
# Silly gdb requirement.
""
""""""
set_doc = "Set width of tabs in the source window."
show_doc = "Show width of tabs in the source window."
def __init__(self):
super(_Tabs, self).__init__('%s', 'tab-width', 8,
gdb.COMMAND_NONE, gdb.PARAM_ZINTEGER)
super(_Tabs, self).__init__(
"%s", "tab-width", 8, gdb.COMMAND_NONE, gdb.PARAM_ZINTEGER
)
@in_gdb_thread
def get_show_string(self, pvalue):
@@ -261,40 +284,45 @@ class _Tabs(_StoredParameter):
gui.toplevel.state.set_tab_width(self.value)
return ""
class _StopNotification(_StoredParameter):
# Silly gdb requirement.
""
""""""
set_doc = "Set whether stop notifications are displayed."
show_doc = "Show whether stop notifications are displayed."
def __init__(self):
super(_StopNotification, self).__init__('%s', 'stop-notification', True,
gdb.COMMAND_RUNNING,
gdb.PARAM_BOOLEAN)
super(_StopNotification, self).__init__(
"%s", "stop-notification", True, gdb.COMMAND_RUNNING, gdb.PARAM_BOOLEAN
)
@in_gdb_thread
def get_show_string(self, pvalue):
return "Whether stop notifications are displayed is: %s" % self.value
class _StopNotificationSeconds(_StoredParameter):
# Silly gdb requirement.
""
""""""
set_doc = "Set stop notification timeout in seconds."
show_doc = "Show stop notification timeout."
def __init__(self):
super(_StopNotificationSeconds, self).__init__('%s',
'stop-notification-seconds',
120,
gdb.COMMAND_RUNNING,
gdb.PARAM_ZINTEGER)
super(_StopNotificationSeconds, self).__init__(
"%s",
"stop-notification-seconds",
120,
gdb.COMMAND_RUNNING,
gdb.PARAM_ZINTEGER,
)
@in_gdb_thread
def get_show_string(self, pvalue):
return "Stop notifications are displayed after %d seconds." % self.value
_SetBase()
_SetTitleBase()
_ShowBase()
@@ -304,10 +332,10 @@ font_manager = _Font()
stop_notification = _StopNotification()
stop_notification_seconds = _StopNotificationSeconds()
_Title('source', '\\W{basename} [GDB Source @\\W{number}]')
_Title('display', '\\W{command} [GDB Display @\\W{number}]')
_Title('log', '[GDB Log @\\W{number}]\\W{default}')
_Title('stack', '[GDB Stack @\\W{number}]')
_Title("source", "\\W{basename} [GDB Source @\\W{number}]")
_Title("display", "\\W{command} [GDB Display @\\W{number}]")
_Title("log", "[GDB Log @\\W{number}]\\W{default}")
_Title("stack", "[GDB Stack @\\W{number}]")
warn_missing = _Missing()
line_numbers = _Lines()

View File

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

View File

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

View File

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

View File

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

View File

@@ -25,6 +25,7 @@ import threading
from gi.repository import Pango
from gui.startup import in_gdb_thread, in_gtk_thread
class _ToplevelState(object):
def __init__(self):
gui.startup.start_gtk()
@@ -73,12 +74,11 @@ class _ToplevelState(object):
print("No windows")
return
print(' Num Name')
print(" Num Name")
for winno in range(1, self.next_toplevel):
if winno in self.toplevels:
window = self.toplevels[winno]
print(' %3d %s' % (window.number,
window.window.get_title()))
print(" %3d %s" % (window.number, window.window.get_title()))
@in_gtk_thread
def _do_set_font(self, font_name):
@@ -125,15 +125,17 @@ class _ToplevelState(object):
def windows(self):
return list(self.toplevels.values())
state = _ToplevelState()
class Toplevel(object):
def __init__(self, window_type):
state.add(self, window_type)
# The subclass must set this.
self.window = None
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)
@in_gtk_thread
@@ -145,7 +147,7 @@ class Toplevel(object):
@in_gtk_thread
def _do_gtk_initialize(self):
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)
if geom:
self.window.parse_geometry(geom)
@@ -158,7 +160,7 @@ class Toplevel(object):
@in_gtk_thread
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))
return False

View File

@@ -21,6 +21,7 @@ from gui.startup import in_gdb_thread, in_gtk_thread
import gdb
import gui.events
class UpdateWindow(Toplevel):
"""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"