@@ -262,8 +262,7 @@ impl Component for Completion {
262 .cursor(doc.text().slice(..));
262 .cursor(doc.text().slice(..));
263 let cursor_pos = (helix_core::coords_at_pos(doc.text().slice(..), cursor_pos).row
263 let cursor_pos = (helix_core::coords_at_pos(doc.text().slice(..), cursor_pos).row
264 - view.offset.row) as u16;
264 - view.offset.row) as u16;
266− let mut doc = match &option.documentation {
265+ let mut markdown_doc = match &option.documentation {
267 Some(lsp::Documentation::String(contents))
266 Some(lsp::Documentation::String(contents))
268 | Some(lsp::Documentation::MarkupContent(lsp::MarkupContent {
267 | Some(lsp::Documentation::MarkupContent(lsp::MarkupContent {
269 kind: lsp::MarkupKind::PlainText,
268 kind: lsp::MarkupKind::PlainText,
@@ -311,24 +310,42 @@ impl Component for Completion {
311 None => return,
310 None => return,
314− let half = area.height / 2;
313+ let (popup_x, popup_y) = self.popup.get_rel_position(area, cx);
315− let height = 15.min(half);
314+ let (popup_width, _popup_height) = self.popup.get_size();
316− // we want to make sure the cursor is visible (not hidden behind the documentation)
315+ let mut width = area
317− let y = if cursor_pos + area.y
316+ .width
318− >= (cx.editor.tree.area().height - height - 2/* statusline + commandline */)
317+ .saturating_sub(popup_x)
319− {
318+ .saturating_sub(popup_width);
320− 0
319+ let area = if width > 30 {
320+ let mut height = area.height.saturating_sub(popup_y);
321+ let x = popup_x + popup_width;
324+ if let Some((rel_width, rel_height)) = markdown_doc.required_size((width, height)) {
326+ height = rel_height;
328+ Rect::new(x, y, width, height)
330+ let half = area.height / 2;
331+ let height = 15.min(half);
332+ // we want to make sure the cursor is visible (not hidden behind the documentation)
333+ let y = if cursor_pos + area.y
334+ >= (cx.editor.tree.area().height - height - 2/* statusline + commandline */)
322− // -2 to subtract command line + statusline. a bit of a hack, because of splits.
338+ // -2 to subtract command line + statusline. a bit of a hack, because of splits.
323− area.height.saturating_sub(height).saturating_sub(2)
339+ area.height.saturating_sub(height).saturating_sub(2)
326− let area = Rect::new(0, y, area.width, height);
342+ Rect::new(0, y, area.width, height)
328 // clear area
345 // clear area
329 let background = cx.editor.theme.get("ui.popup");
346 let background = cx.editor.theme.get("ui.popup");
330 surface.clear_with(area, background);
347 surface.clear_with(area, background);
331− doc.render(area, surface, cx);
348+ markdown_doc.render(area, surface, cx);