daa84 / neovim-gtk

gtk ui for neovim
GNU General Public License v3.0
718 stars 56 forks source link

GUI pop-up menu doesn't work well with YouCompleteMe(Semantic completion engine) #34

Closed ammen99 closed 5 years ago

ammen99 commented 6 years ago

Just as I said in the title, works with the built-in(text-based) menu, but not with the nice GUI one. It is rendered in an invisible location, see the screenshot for a better understanding. The problem is in the interaction with YouCompleteMe (I tried removing all other options and plugins and it still didn't work). Without YCM the built-in menu(with ) works well enough, but with YCM also doesn't work. screenshot-2017-12-10-21 36 40

The menu is actually bigger than it should be, so it gets outside the window and the screen. I tried moving the window to the side, but the menu is much bigger, so I haven't been able to see its beginning. My guess without looking at the code is that the pop-up menu doesn't "prune" autocomplete items' length, but the reason might be somewhere else.

ammen99 commented 6 years ago

Just to confirm my suspicion: the built-in completion () also doesn't work with GUI popups if I create an identifier of huge length (on my resolution and font that's around 450 characters)

ammen99 commented 6 years ago

I decided to try hacking into the code to see if I could solve the problem(which I did). However, what I did isn't generic enough(It works only with YCM because it has 4 columns for autocomplete). I'm using the following:

       for line in menu {
            let mut line_array = Vec::new();
            let max_col_length = [100, 5, 40, 0];

            let mut i = 0;
            for &item in line {
                let (short, _) =
                    if item.len() > max_col_length[i]
                        { item.split_at(max_col_length[i]) }
                    else
                        { (item, "") };

                line_array.push(short);
                i = i + 1;
            }

            let larr : Vec<&glib::ToValue> =
                line_array.iter().map(|v| v as &glib::ToValue).collect();

            list_store.insert_with_values(None, &all_column_ids, &larr[..]);
        }

Of course, this ignores the fourth column completely, because I personally don't need it. If you want to fix this in the code, then maybe there should be a maximum width based on width width and font, then add columns until we fill this size(not like the constants in the beginning). I also believe there will be a better way to write this, it is actually my first rust code :) anyway, a great app :+1:

daa84 commented 6 years ago

Limitation of column widths is better do with cell renderers instead of cutting column content, as renderers provide some visual feedback to user that content is bigger than displayed.

Good solution for this issue can be to enable horizontal scroll with some maximum popup window width. Also replace column kind with icon and maybe display column info in some separate popup or add some special info panel to this popup that display info only for selected item.

daa84 commented 6 years ago

Some steps to fix the problem: enable horizontal scroll with maximum width of popup set to bit smaller than window width. Also extract info column to label under popup.

I don't know is there option in neovim to set exact column widths? Maybe introduce new one just for NeovimGtk...

ammen99 commented 6 years ago

@daa84 Thanks, this resolves the pop-up being too big. However, it would be ideal to have option to set individual column maximum and to disable the label in this case(because I would like to see member fields' type right next to their names). I'm not aware of such functionality in neovim, but IMHO it will be a great addition to NeovimGtk. At least we can introduce some limit for the "word" column based on font size or some better heuristic so that we can see the "kind" at least. Probably possible with the GtkTreeView sizing policy(https://developer.gnome.org/gtk3/stable/GtkTreeViewColumn.html#gtk-tree-view-column-set-sizing for the C function, possibly there is some equivalent for Rust)

daa84 commented 6 years ago

Added some calculation, so word and kind column must be always visible. Can't say what to do with label, maybe some NeovimGtk specific option.

ammen99 commented 6 years ago

This seems to work, thanks :+1:

Another suggestion in relation to this issue - when there is a kind column, don't try to take up all the space(resizing at max_width). What I mean is that for example in the following: screenshot-2018-01-08-21 22 52

The word column in this particular case(because all "words" are much shorter than the window width) can be made much smaller and this would allow the menu/label/whatever column to be visible as well. This is as simple as the following snippet(maybe should be rewritten if you decide to implement it this way):

        if kind_chars > 0 { 
            layout.set_text("[v]");
            let (kind_width, _) = layout.get_pixel_size();

            let max_line = menu.iter().max_by_key(|m| m.word.len()).unwrap();
            layout.set_text(max_line.word);

            let (word_need_width, _) = layout.get_pixel_size();
            let word_max_width = max_width - kind_width;
            let word_width = min(word_max_width, word_need_width + xpad * 2 + DEFAULT_PADDING);                                                   

            self.word_column.set_fixed_width(word_width);

            self.kind_column.set_fixed_width(kind_width + xpad * 2 + DEFAULT_PADDING);
            self.kind_column.set_visible(true);
        }
ammen99 commented 6 years ago

Also about label: maybe there should be a neovim-gtk specific option. I actually patch nvim-gtk so I don't see it because I don't like how it changes the height of the popup, but I figure that some people would find it really useful and even necessary.

daa84 commented 6 years ago

Ups, yes, width calculation a was wrong, fixed.

ammen99 commented 6 years ago

Works like a charm. Now, I "remembered" something which would be a good indicator whether to show the label: set completeopt-=preview

I have this in my init.vim. Basically, what nvim-gtk displays in the label is what terminal neovim shows in a split preview window. Using the option above I can disable the preview window, so it seems logical that it should also disable the label(I checked and nvim-gtk doesn't show preview at all anyway, regardless of whether I add preview to completeopt or not).