Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How can I write a hook to display variable number of items in the watch window? #50

Closed
typon opened this issue Oct 14, 2021 · 3 comments
Labels
enhancement New feature or request

Comments

@typon
Copy link

typon commented Oct 14, 2021

I am trying to write a display hook in python for a dynamic array container (for example std::vector).

The way I understand the hook function is that it is called twice: once to fetch the list of names of the fields, and another time to fetch their respective values.

I would like to display each item in my dynamic array as a separate element in this list of fields. I can't figure out how to change the gf code such that by the time it calls the hook with field = None, I already know the number of elements in my array.

Any help would be greatly appreciated.

@nakst
Copy link
Owner

nakst commented Oct 14, 2021

This is currently not possible to do; the watch window API needs to be expanded first. Do you have any suggestions on what it should look like?

@typon
Copy link
Author

typon commented Oct 14, 2021

It took me a while to wrap my head around what the current API is attempting to do...my suggestion would be to make it a lot more explicit.

What about something like this:

from typing import Callable
from abc import ABC, abstractmethod

class WatchHook(ABC):
    @abstractmethod
    def get_short_name(self, expression_value: gdb.Value):
        raise NotImplementedError("must override!")

    @abstractmethod
    def get_row_names(self, expression_value: gdb.Value):
        raise NotImplementedError("must override!")

    @abstractmethod
    def get_row_values(self, expression_value: gdb.Value):
        raise NotImplementedError("must override!")

# Sample array hook
class ArrayHook(WatchHook):
    def get_short_name(self, array_value: gdb.Value):
        # TODO: Extract size of array here
        return f"Array of {array_size} items"

    def get_row_names(self, array_value: gdb.Value):
        """
        This method is called `get_row_names` and not `get_field_names` because
        the user can use these for any purpose, for example indices of an array
        """
        # TODO: Extract size of array here
        self.array_size = array_size
        return [str(index) for index in range(0, array_size)]

    def get_row_values(self, value_stringify_callback: Callable, array_value: gdb.Value):
        result = []
        for index in range(self.array_size):
            value: gdb.Value = array_value[index]
            # This callback will recursively call other registered hooks or the default hook
            # to get the string to be displayed
            # In the case where array items are structs or other nested objects,
            # the callback will insert the short_name here and mark this row as expandable
            value_str: str = value_stringify_callback(value)
            result.append(value_str)
        return result

I don't understand the rest of the gf code enough to actually implement this myself, unfortunately :( I am willing to help though.

@nakst nakst added the enhancement New feature or request label Oct 24, 2021
@nakst
Copy link
Owner

nakst commented Nov 2, 2021

I've added this in 982176e and documented it in c3aa0fb.
However I have not had a chance to test it much yet, so I'll keep this issue open for now in case there are bugs.

@nakst nakst closed this as completed Nov 8, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants