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

The eldoc-box-frame-hook might be broken and how to draw a border around the child frame #100

Open
shipmints opened this issue May 23, 2024 · 13 comments

Comments

@shipmints
Copy link

Thank you for this nice little package. Curious if the following is a bug, and, if not, what one should do instead. I'd like to draw a white border in the child frame. I'm emacs 29.3 on an intel mac, in case the mac drawing code is at fault. I do not have another platform on which to test.

In the function

(defun eldoc-box--get-frame (buffer)
...
      (with-selected-frame frame
        (run-hook-with-args 'eldoc-box-frame-hook main-frame))
      (make-frame-visible frame))))

it seems to me that the hook should be called with the child frame and not the main frame?

Shouldn't this work?

  (defun my/eldoc-box-post-frame-hook (frame)
    (modify-frame-parameters
     eldoc-box--frame ; frame here is the main-frame so force internal reference
     `((internal-border-width . ,1))
     )
    )
  (add-hook 'eldoc-box-frame-hook #'my/eldoc-box-post-frame-hook)

By the way, the hacked version doesn't seem to work, either. So maybe it is the mac drawing code at fault?

@casouri
Copy link
Owner

casouri commented May 24, 2024

I looked at my config and I just have

(set-face-attribute 'eldoc-box-border nil :background "darkgray")

Give that a try and see it if works for you.

@shipmints
Copy link
Author

shipmints commented May 24, 2024

Hi, and thank you for taking a look. No box border appears at all. The effect I'm trying to achieve is a white box around the pop-up. I've attached a screenshot of what it looks like. I set the height to 0.85 so it's clearly a tooltip (I've done the same for corfu-default). The theme is modus-vivendi from the 29.3 distribution (not prot's latest) if that has any bearing.

image

Something like this (but only one pixel, ofc (I'd also like a box around the corfu popup, too):

image

@shipmints
Copy link
Author

I still wonder if the hook is being called with a reference to the correct child frame or not.

@casouri
Copy link
Owner

casouri commented May 24, 2024

I still wonder if the hook is being called with a reference to the correct child frame or not.

It's working as expected; the docstring says "Each function runs inside the new frame and receives the main frame as argument". So if you want to reference the childframe, you should use current-frame.

If my config doesn't work, then it's probably Emacs 29 on Mac not drawing the border properly. (I remember it not working in the past but I don't remember since when it starts to work :-) Maybe try Emacs master?

@shipmints
Copy link
Author

I'll keep at it.

@shipmints
Copy link
Author

This works for me BUT I still don't get why the hook is being passed the frame of the buffer window vs. the child frame.

  (defun my/eldoc-box-post-frame-hook (frame)
    (modify-frame-parameters
     ;; the hook sends the parent frame this is not what we want we force the child frame
     eldoc-box--frame
     `(
       (background-color . "white")
       (internal-border-width . ,1)
       )
     )
    )
  (add-hook 'eldoc-box-frame-hook #'my/eldoc-box-post-frame-hook)

@shipmints
Copy link
Author

FYI, this cosmetic hack now also eliminates fringes because they create weird visual artifacts in the child frame.

  (defun my/eldoc-box-post-frame-hook (_frame)
    (modify-frame-parameters
     ;; the hook sends the parent frame this is not what we want we force the child frame
     eldoc-box--frame
     `(
       (left-fringe . ,0)
       (right-fringe . ,0)
       (background-color . "white")
       (internal-border-width . ,1)
       )))
  (add-hook 'eldoc-box-frame-hook #'my/eldoc-box-post-frame-hook)

@casouri
Copy link
Owner

casouri commented Jan 8, 2025

What kind of visual artifacts? Maybe I can fix it without disabling fringes. I kept the left and right fringe so there's a little gap between the text and the border, otherwise the text is right against the border and it doesn't look good.

Internal border would've been the best way to create padding around the text, but we use it for displaying border because childframe doesn't support external border IIRC.

@casouri
Copy link
Owner

casouri commented Jan 8, 2025

This works for me BUT I still don't get why the hook is being passed the frame of the buffer window vs. the child frame.

Regarding that, it's mainly to have access to both the original buffer and the childframe. Since the hook is called in the child frame (so we already have access to it), we pass the original frame as a parameter.

@shipmints
Copy link
Author

Here's a screenshot with fringes left enabled.

image

And one with fringes disabled.

image

It's also not very nice that the text in the box doesn't wrap properly so some words before eol are put on the next line despite there being plenty of space. Not sure where to look for the culprit.

@casouri
Copy link
Owner

casouri commented Jan 10, 2025

Hmm, so it's the line-wrap marker. But as you observed, the line shouldn't wrap in the first place. eldoc-box should resize the frame to fit all content, and in this case there're clearly enough room. Could you send me this text? Just click inside the childframe, and C-x h copy all the text in the buffer. I want to see if there's anything funny in the text.

@shipmints
Copy link
Author

Verbatim:

DataFrame(data=None, index: 'Axes | None'=None, columns: 'Axes | None'=None, dtype: 'Dtype | None'=None, copy: 'bool | None'=None)

Two-dimensional, size-mutable, potentially heterogeneous tabular data.

Data structure also contains labeled axes (rows and columns).
Arithmetic operations align on both row and column labels. Can be
thought of as a dict-like container for Series objects. The primary
pandas data structure.

#### Parameters

- data: ndarray (structured or homogeneous), Iterable, dict, or DataFrame
    Dict can contain Series, arrays, constants, dataclass or list-like objects. If
    data is a dict, column order follows insertion-order. If a dict contains Series
    which have an index defined, it is aligned by its index. This alignment also
    occurs if data is a Series or a DataFrame itself. Alignment is done on
    Series/DataFrame inputs.

    If data is a list of dicts, column order follows insertion-order.

- index: Index or array-like
    Index to use for resulting frame. Will default to RangeIndex if
    no indexing information part of input data and no index provided.
- columns: Index or array-like
    Column labels to use for resulting frame when data does not have them,
    defaulting to RangeIndex(0, 1, 2, ..., n). If data contains column labels,
    will perform column selection instead.
- dtype: dtype, default None
    Data type to force. Only a single dtype is allowed. If None, infer.
- copy: bool or None, default None
    Copy data from inputs.
    For dict data, the default of None behaves like copy=True.  For DataFrame
    or 2d ndarray input, the default of None behaves like copy=False.
    If data is a dict containing one or more Series (possibly of different dtypes),
    copy=False will ensure that these inputs are not copied.

    Changed in 1.3.0

#### See Also

- DataFrame.from_records: Constructor from tuples, also record arrays.
- DataFrame.from_dict: From dicts of Series, arrays, or dicts.
- read_csv: Read a comma-separated values (csv) file into DataFrame.
- read_table: Read general delimited file into DataFrame.
- read_clipboard: Read text from clipboard into DataFrame.

#### Notes

Please reference the User Guide: basics.dataframe for more information.

#### Examples

Constructing DataFrame from a dictionary.

d = {'col1': [1, 2], 'col2': [3, 4]}
df = pd.DataFrame(data=d)
df

   col1  col2
0     1     3
1     2     4

Notice that the inferred dtype is int64.

df.dtypes

col1    int64
col2    int64
dtype: object

To enforce a single dtype:

df = pd.DataFrame(data=d, dtype=np.int8)
df.dtypes

col1    int8
col2    int8
dtype: object

Constructing DataFrame from a dictionary including Series:

d = {'col1': [0, 1, 2, 3], 'col2': pd.Series([2, 3], index=[2, 3])}
pd.DataFrame(data=d, index=[0, 1, 2, 3])

   col1  col2
0     0   NaN
1     1   NaN
2     2   2.0
3     3   3.0

Constructing DataFrame from numpy ndarray:

df2 = pd.DataFrame(np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]),
                   columns=['a', 'b', 'c'])
df2

   a  b  c
0  1  2  3
1  4  5  6
2  7  8  9

Constructing DataFrame from a numpy ndarray that has labeled columns:

data = np.array([(1, 2, 3), (4, 5, 6), (7, 8, 9)],
                dtype=[("a", "i4"), ("b", "i4"), ("c", "i4")])
df3 = pd.DataFrame(data, columns=['c', 'a'])

df3

   c  a
0  3  1
1  6  4
2  9  7

Constructing DataFrame from dataclass:

from dataclasses import make_dataclass
Point = make_dataclass("Point", [("x", int), ("y", int)])
pd.DataFrame([Point(0, 0), Point(0, 3), Point(2, 3)])

   x  y
0  0  0
1  0  3
2  2  3

Constructing DataFrame from Series/DataFrame:

ser = pd.Series([1, 2, 3], index=["a", "b", "c"])
df = pd.DataFrame(data=ser, index=["a", "c"])
df

   0
a  1
c  3

df1 = pd.DataFrame([1, 2, 3], index=["a", "b", "c"], columns=["x"])
df2 = pd.DataFrame(data=df1, index=["a", "c"])
df2

   x
a  1
c  3

@shipmints
Copy link
Author

shipmints commented Jan 10, 2025

This could be a hint. I have global-hl-line-mode enabled and you can see it with the subtle dark gray bar over the word "data". It looks like the window width and the frame width are divergent.

image

Could disable truncate long lines in the doc buffer?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants