public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
From: Hannes Domani <ssbssa@yahoo.de>
To: gdb-patches@sourceware.org
Subject: [PATCH 22/22] Copy variable value to clipboard on middle-click
Date: Sat,  6 Mar 2021 18:44:50 +0100	[thread overview]
Message-ID: <20210306174450.21718-3-ssbssa@yahoo.de> (raw)
In-Reply-To: <20210306174450.21718-1-ssbssa@yahoo.de>

For variables that don't have children, or the children tree is closed, its
text representation is copied.
If the variable has children, and the children tree is opened, the text
representation of the children is copied instead (each on a separate line).

I could imagine customizable actions on middle-click on VariableWindow
variables, like some kind of callback function.

I chose the clipboard myself because I relatively often have classes for
graphical objects like lines and arcs.
For easier readability, I created simple pretty printers, like:

    LINE 0 0 100 0
    ARC 50 0 50 0 3.1415

So a middle-click on an opened vector containing these objects copies their
text representation to the clipboard.

I have another tool that is notified whenever the clipboard contents change,
and if they are in this specific format, immediately visualizes them.

The result is a relatively convenient way to visualize these graphical objects
from the debugger, with a single mouse-click.
---
 gdb/python/lib/gdb/command/tui_windows.py | 76 +++++++++++++++++++++++
 1 file changed, 76 insertions(+)

diff --git a/gdb/python/lib/gdb/command/tui_windows.py b/gdb/python/lib/gdb/command/tui_windows.py
index 45ba9502878..050ef4d1ddf 100644
--- a/gdb/python/lib/gdb/command/tui_windows.py
+++ b/gdb/python/lib/gdb/command/tui_windows.py
@@ -23,6 +23,62 @@ PY3 = sys.version_info[0] == 3
 custom_windows = {}
 
 
+if sys.platform == 'win32':
+    import ctypes
+    import ctypes.wintypes as w
+
+    CF_TEXT = 1
+
+    u32 = ctypes.WinDLL('user32')
+    k32 = ctypes.WinDLL('kernel32')
+
+    OpenClipboard = u32.OpenClipboard
+    OpenClipboard.argtypes = w.HWND,
+    OpenClipboard.restype = w.BOOL
+
+    EmptyClipboard = u32.EmptyClipboard
+    EmptyClipboard.restype = w.BOOL
+
+    SetClipboardData = u32.SetClipboardData
+    SetClipboardData.argtypes = w.UINT, w.HANDLE,
+    SetClipboardData.restype = w.HANDLE
+
+    CloseClipboard = u32.CloseClipboard
+    CloseClipboard.restype = w.BOOL
+
+    GHND = 0x0042
+
+    GlobalAlloc = k32.GlobalAlloc
+    GlobalAlloc.argtypes = w.UINT, ctypes.c_size_t,
+    GlobalAlloc.restype = w.HGLOBAL
+
+    GlobalLock = k32.GlobalLock
+    GlobalLock.argtypes = w.HGLOBAL,
+    GlobalLock.restype = w.LPVOID
+
+    GlobalUnlock = k32.GlobalUnlock
+    GlobalUnlock.argtypes = w.HGLOBAL,
+    GlobalUnlock.restype = w.BOOL
+
+    def set_clipboard_text(s):
+        if OpenClipboard(None):
+            s = s.encode('utf-8')
+            EmptyClipboard()
+            h = GlobalAlloc(GHND, len(s) + 1)
+            p = GlobalLock(h)
+            ctypes.memmove(p, s, len(s))
+            GlobalUnlock(h)
+            SetClipboardData(CF_TEXT, h)
+            CloseClipboard()
+
+else:
+    import base64
+
+    def set_clipboard_text(s):
+        b64 = base64.b64encode(s.encode('utf-8')).decode()
+        sys.__stdout__.write("\x1b]52;c;" + b64 + "\x07")
+
+
 col_esc_seq_re = re.compile('(\033\[[0-9;]*m)')
 def escaped_substr(s, n, c):
     col_esc_seq = False
@@ -189,6 +245,26 @@ class VariableWindow(TextWindow):
                 if prev is not None and prev[3] is not None:
                     gdb.set_convenience_variable(self.convenience_name, prev[3])
                     self.refill(True)
+        elif button == 2 and line < len(self.line_names):
+            name = self.line_names[line]
+            if name:
+                prev = self.prev_vals[name]
+                if prev is not None:
+                    if prev[0]:
+                        name2 = name + ":"
+                        child_texts = []
+                        for l in range(line + 1, len(self.line_names)):
+                            child_name = self.line_names[l]
+                            if not child_name:
+                                continue
+                            if not child_name.startswith(name2):
+                                break
+                            child = self.prev_vals[child_name]
+                            if child is not None and child[1] != False:
+                                child_texts.append(child[1])
+                        set_clipboard_text("\n".join(child_texts))
+                    elif prev[1] != False:
+                        set_clipboard_text(prev[1])
 
     def refill(self, keep_prev=False):
         if not self.win.is_valid():
-- 
2.30.1


  parent reply	other threads:[~2021-03-06 17:45 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <20210306174450.21718-1-ssbssa.ref@yahoo.de>
2021-03-06 17:44 ` [PATCH 20/22] Use method children instead of to_string in pretty printers Hannes Domani
2021-03-06 17:44   ` [PATCH 21/22] Implement memory TUI window Hannes Domani
2021-03-06 17:44   ` Hannes Domani [this message]
2021-03-11 21:55   ` [PATCH 20/22] Use method children instead of to_string in pretty printers Tom Tromey

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210306174450.21718-3-ssbssa@yahoo.de \
    --to=ssbssa@yahoo.de \
    --cc=gdb-patches@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).