Repository: helix-editor/helix
File: helix-term/src/commands/lsp.rs (Rust)

Code before:

            let doc_text = doc.text();
            let inlay_hints_length_limit = doc.config.load().lsp.inlay_hints_length_limit;

            for hint in hints {
                let char_idx =
                    match helix_lsp::util::lsp_pos_to_pos(doc_text, hint.position, offset_encoding)
                    {
                        Some(pos) => pos,
                        // Skip inlay hints that have no "real" position
                        None => continue,
                    };

                let label = {
                    let mut label = match hint.label {
                        lsp::InlayHintLabel::String(s) => s,
                        lsp::InlayHintLabel::LabelParts(parts) => parts
                            .into_iter()
                            .map(|p| p.value)
                            .collect::<Vec<_>>()
                            .join(""),
                    };
                    // Truncate the hint if too long
                    if let Some(limit) = inlay_hints_length_limit {
                        let limit = limit.into();
                        if label.len() > limit {
                            label.truncate(limit);
                            label.push_str("..");
                        }
                    }

                    label
                };

                let inlay_hints_vec = match hint.kind {
                    Some(lsp::InlayHintKind::TYPE) => &mut type_inlay_hints,
                    Some(lsp::InlayHintKind::PARAMETER) => &mut parameter_inlay_hints,
                    // We can't warn on unknown kind here since LSPs are free to set it or not, for
                    // example Rust Analyzer does not: every kind will be `None`.
                    _ => &mut other_inlay_hints,
                };

                if let Some(true) = hint.padding_left {
                    padding_before_inlay_hints.push(InlineAnnotation::new(char_idx, " "));
                }

                inlay_hints_vec.push(InlineAnnotation::new(char_idx, label));

                if let Some(true) = hint.padding_right {
                    padding_after_inlay_hints.push(InlineAnnotation::new(char_idx, " "));
                }

Review comment (suggestion):
The byte length of the string works ok for ASCII but this should be checking width from `UnicodeWidthStr` to figure out how many Unicode grapheme clusters can fit within the limit.

Code after:

            let doc_text = doc.text();
            let inlay_hints_length_limit = doc.config.load().lsp.inlay_hints_length_limit;

            for hint in hints {
                let char_idx =
                    match helix_lsp::util::lsp_pos_to_pos(doc_text, hint.position, offset_encoding)
                    {
                        Some(pos) => pos,
                        // Skip inlay hints that have no "real" position
                        None => continue,
                    };

                let mut label = match hint.label {
                    lsp::InlayHintLabel::String(s) => s,
                    lsp::InlayHintLabel::LabelParts(parts) => parts
                        .into_iter()
                        .map(|p| p.value)
                        .collect::<Vec<_>>()
                        .join(""),
                };
                // Truncate the hint if too long
                if let Some(limit) = inlay_hints_length_limit {
                    // Limit on displayed width
                    use helix_core::unicode::{
                        segmentation::UnicodeSegmentation, width::UnicodeWidthStr,
                    };

                    let width = label.width();
                    let limit = limit.get().into();
                    if width > limit {
                        let mut floor_boundary = 0;
                        let mut acc = 0;
                        for (i, grapheme_cluster) in label.grapheme_indices(true) {
                            acc += grapheme_cluster.width();

                            if acc > limit {
                                floor_boundary = i;
                                break;
                            }
                        }

                        label.truncate(floor_boundary);
                        label.push('…');
                    }
                }

                let inlay_hints_vec = match hint.kind {
                    Some(lsp::InlayHintKind::TYPE) => &mut type_inlay_hints,
                    Some(lsp::InlayHintKind::PARAMETER) => &mut parameter_inlay_hints,
                    // We can't warn on unknown kind here since LSPs are free to set it or not, for