Repository: helix-editor/helix
File: helix-term/src/ui/completion.rs (Rust)

Code before:
                Some(lsp::CompletionItemKind::FOLDER) => "folder".into(),
                Some(lsp::CompletionItemKind::ENUM_MEMBER) => "enum_member".into(),
                Some(lsp::CompletionItemKind::CONSTANT) => "constant".into(),
                Some(lsp::CompletionItemKind::STRUCT) => "struct".into(),
                Some(lsp::CompletionItemKind::EVENT) => "event".into(),
                Some(lsp::CompletionItemKind::OPERATOR) => "operator".into(),
                Some(lsp::CompletionItemKind::TYPE_PARAMETER) => "type_param".into(),
                Some(kind) => {
                    log::error!("Received unknown completion item kind: {:?}", kind);
                    "".into()
                }
                None => "".into(),
            },
            CompletionItem::Other(core::CompletionItem { kind, .. }) => Span::raw(kind.to_string()),
        };

        menu::Row::new([
            menu::Cell::from(Span::styled(
                label,
                if deprecated {
                    Style::default().add_modifier(Modifier::CROSSED_OUT)
                } else {
                    Style::default()
                },
            )),
            if kind.content == "■" {
                menu::Cell::from(Spans::from(vec![Span::raw("color "), kind]))
            } else {
                menu::Cell::from(kind)
            },
        ])
    }
}

/// Wraps a Menu.
pub struct Completion {
    popup: Popup<Menu<CompletionItem>>,
    #[allow(dead_code)]
    trigger_offset: usize,
    filter: String,
    resolve_handler: ResolveHandler,
}

impl Completion {
    pub const ID: &'static str = "completion";

    pub fn new(
        editor: &Editor,
        savepoint: Arc<SavePoint>,
        mut items: Vec<CompletionItem>,
        trigger_offset: usize,

Review comment (suggestion):
When converting to a `Cell` the content is wrapped in two Vecs so avoiding `Spans` above doesn't end up saving any allocations. Instead let's have `kind` be `Spans` and let `.into()` take care of the conversions

Code after:
                Some(lsp::CompletionItemKind::CONSTANT) => "constant".into(),
                Some(lsp::CompletionItemKind::STRUCT) => "struct".into(),
                Some(lsp::CompletionItemKind::EVENT) => "event".into(),
                Some(lsp::CompletionItemKind::OPERATOR) => "operator".into(),
                Some(lsp::CompletionItemKind::TYPE_PARAMETER) => "type_param".into(),
                Some(kind) => {
                    log::error!("Received unknown completion item kind: {:?}", kind);
                    "".into()
                }
                None => "".into(),
            },
            CompletionItem::Other(core::CompletionItem { kind, .. }) => kind.as_ref().into(),
        };

        let label = Span::styled(
            label,
            if deprecated {
                Style::default().add_modifier(Modifier::CROSSED_OUT)
            } else if kind.0[0].content == "folder" {
                *dir_style
            } else {
                Style::default()
            },
        );

        menu::Row::new([menu::Cell::from(label), menu::Cell::from(kind)])
    }
}

/// Wraps a Menu.
pub struct Completion {
    popup: Popup<Menu<CompletionItem>>,
    #[allow(dead_code)]
    trigger_offset: usize,
    filter: String,
    resolve_handler: ResolveHandler,
}

impl Completion {
    pub const ID: &'static str = "completion";

    pub fn new(
        editor: &Editor,
        savepoint: Arc<SavePoint>,
        mut items: Vec<CompletionItem>,
        trigger_offset: usize,
    ) -> Self {
        let preview_completion_insert = editor.config().preview_completion_insert;
        let replace_mode = editor.config().completion_replace;
        // Sort completion items according to their preselect status (given by the LSP server)
        items.sort_by_key(|item| !item.preselect());