mirror of
https://github.com/enso-org/enso.git
synced 2024-12-23 21:12:44 +03:00
Show default per-kind icons for all entries in Component Browser. (#3587)
Show default icons for all entries in the Component Browser. The icons are assigned to each entry depending on its kind. https://www.pivotaltracker.com/story/show/182584326 #### Visuals See below for a video showing entries of 5 different kinds in the Component Browser, each having a different icon. When watching the video, please note that the following are preexisting, known issues, not introduced by this PR: - Selection is misaligned when hovering the mouse over the "new" component in the "Mcdbg Group 1" group - reported as issue 2 [in comments to PR 3530](https://github.com/enso-org/enso/pull/3530#pullrequestreview-1034223437). - [Names of Modules and Atoms displayed in Component Browser start with a small letter.](https://www.pivotaltracker.com/story/show/182745386) https://user-images.githubusercontent.com/273837/179016109-c3ebab5a-0205-4b44-85b8-df3129edd75d.mov # Important Notes - A new derive macro `ForEachVariant` is defined and added to the `enso-prelude` crate.
This commit is contained in:
parent
f699a64c33
commit
07df7fabf2
@ -132,7 +132,7 @@ impl<'a> IntoIterator for &'a QualifiedName {
|
|||||||
// =============
|
// =============
|
||||||
|
|
||||||
/// A type of suggestion entry.
|
/// A type of suggestion entry.
|
||||||
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
#[derive(Copy, Clone, Debug, Eq, PartialEq, ForEachVariant)]
|
||||||
#[allow(missing_docs)]
|
#[allow(missing_docs)]
|
||||||
pub enum Kind {
|
pub enum Kind {
|
||||||
Atom,
|
Atom,
|
||||||
|
@ -157,6 +157,12 @@ impl ide_view::searcher::DocumentationProvider for Action {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// ===========================
|
||||||
|
// === provider::Component ===
|
||||||
|
// ===========================
|
||||||
|
|
||||||
/// Component Provider getting entries from a [`controller::searcher::component::Group`].
|
/// Component Provider getting entries from a [`controller::searcher::component::Group`].
|
||||||
#[derive(Clone, CloneRef, Debug)]
|
#[derive(Clone, CloneRef, Debug)]
|
||||||
pub struct Component {
|
pub struct Component {
|
||||||
@ -170,23 +176,40 @@ impl Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
macro_rules! kind_to_icon {
|
||||||
|
([ $( $variant:ident ),* ] $kind:ident) => {
|
||||||
|
{
|
||||||
|
use component_group_view::icon::Id;
|
||||||
|
use suggestion_database::entry::Kind;
|
||||||
|
match $kind {
|
||||||
|
$( Kind::$variant => Id::$variant, )*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl list_view::entry::ModelProvider<component_group_view::Entry> for Component {
|
impl list_view::entry::ModelProvider<component_group_view::Entry> for Component {
|
||||||
fn entry_count(&self) -> usize {
|
fn entry_count(&self) -> usize {
|
||||||
self.group.matched_items.get()
|
self.group.matched_items.get()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get(&self, id: usize) -> Option<component_group_view::entry::Model> {
|
fn get(&self, id: usize) -> Option<component_group_view::entry::Model> {
|
||||||
|
use suggestion_database::entry::for_each_kind_variant;
|
||||||
let component = self.group.get_entry(id)?;
|
let component = self.group.get_entry(id)?;
|
||||||
let match_info = component.match_info.borrow();
|
let match_info = component.match_info.borrow();
|
||||||
let label = component.label();
|
let label = component.label();
|
||||||
let highlighted = bytes_of_matched_letters(&*match_info, &label);
|
let highlighted = bytes_of_matched_letters(&*match_info, &label);
|
||||||
|
let kind = component.suggestion.kind;
|
||||||
Some(component_group_view::entry::Model {
|
Some(component_group_view::entry::Model {
|
||||||
icon: component_group_view::icon::Id::AddColumn,
|
icon: for_each_kind_variant!(kind_to_icon(kind)),
|
||||||
highlighted_text: list_view::entry::GlyphHighlightedLabelModel { label, highlighted },
|
highlighted_text: list_view::entry::GlyphHighlightedLabelModel { label, highlighted },
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// === Component Provider helpers ===
|
||||||
|
|
||||||
fn bytes_of_matched_letters(match_info: &MatchInfo, label: &str) -> Vec<text::Range<text::Bytes>> {
|
fn bytes_of_matched_letters(match_info: &MatchInfo, label: &str) -> Vec<text::Range<text::Bytes>> {
|
||||||
if let MatchInfo::Matches { subsequence } = match_info {
|
if let MatchInfo::Matches { subsequence } = match_info {
|
||||||
let mut char_iter = label.char_indices().enumerate();
|
let mut char_iter = label.char_indices().enumerate();
|
||||||
@ -211,6 +234,12 @@ fn bytes_of_matched_letters(match_info: &MatchInfo, label: &str) -> Vec<text::Ra
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// ===========================
|
||||||
|
// === Converter functions ===
|
||||||
|
// ===========================
|
||||||
|
|
||||||
/// Get [`LabeledAnyModelProvider`] for given component group.
|
/// Get [`LabeledAnyModelProvider`] for given component group.
|
||||||
pub fn from_component_group(
|
pub fn from_component_group(
|
||||||
group: &controller::searcher::component::Group,
|
group: &controller::searcher::component::Group,
|
||||||
|
@ -1,4 +1,11 @@
|
|||||||
//! This macro defines set of common macros which are useful across different projects.
|
//! This module defines set of common macros which are useful across different projects.
|
||||||
|
|
||||||
|
|
||||||
|
// ==============
|
||||||
|
// === Export ===
|
||||||
|
// ==============
|
||||||
|
|
||||||
|
pub use enso_shapely::ForEachVariant;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
44
lib/rust/shapely/macros/src/derive_for_each_variant.rs
Normal file
44
lib/rust/shapely/macros/src/derive_for_each_variant.rs
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
//! This module contains the [`derive`] function (implementing the [`crate::ForEachVariant`] derive
|
||||||
|
//! macro) as well as its helper functions.
|
||||||
|
|
||||||
|
use inflector::cases::snakecase::to_snake_case;
|
||||||
|
use proc_macro2::TokenStream;
|
||||||
|
use quote::quote;
|
||||||
|
use syn::punctuated::Punctuated;
|
||||||
|
use syn::Token;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// ======================
|
||||||
|
// === ForEachVariant ===
|
||||||
|
// ======================
|
||||||
|
|
||||||
|
/// Implementation of the `ForEachVariant` derive macro. For details, see the documentation of the
|
||||||
|
/// [`crate::derive_for_each_variant`] function.
|
||||||
|
pub fn derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
||||||
|
let decl = syn::parse_macro_input!(input as syn::DeriveInput);
|
||||||
|
let ret = match decl.data {
|
||||||
|
syn::Data::Enum(ref e) => derive_for_enum(&decl, e),
|
||||||
|
_ => panic!("The `ForEachVariant` derive macro only works on enums."),
|
||||||
|
};
|
||||||
|
proc_macro::TokenStream::from(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn derive_for_enum(decl: &syn::DeriveInput, data: &syn::DataEnum) -> TokenStream {
|
||||||
|
let enum_name = &decl.ident;
|
||||||
|
let enum_snake_name = to_snake_case(&enum_name.to_string());
|
||||||
|
let macro_name = quote::format_ident!("for_each_{}_variant", enum_snake_name);
|
||||||
|
let variant_names: Punctuated<_, Token![,]> = data.variants.iter().map(|v| &v.ident).collect();
|
||||||
|
quote! {
|
||||||
|
/// Calls `f!` passing to it a comma-separated list of names of variants of [`#enum_name`]
|
||||||
|
/// enclosed in square brackets. The extra `args` are passed to `f!` verbatim after the
|
||||||
|
/// closing square bracket. For more details, see the documentation of the
|
||||||
|
/// [`ForEachVariant`] derive macro.
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! #macro_name {
|
||||||
|
( $f:ident($( $args:tt )*) ) => { $f!([ #variant_names ] $($args)*) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) use #macro_name;
|
||||||
|
}
|
||||||
|
}
|
@ -23,6 +23,7 @@ extern crate proc_macro;
|
|||||||
|
|
||||||
mod derive_clone_ref;
|
mod derive_clone_ref;
|
||||||
mod derive_entry_point;
|
mod derive_entry_point;
|
||||||
|
mod derive_for_each_variant;
|
||||||
mod derive_iterator;
|
mod derive_iterator;
|
||||||
mod derive_no_clone;
|
mod derive_no_clone;
|
||||||
mod overlappable;
|
mod overlappable;
|
||||||
@ -114,6 +115,38 @@ pub fn derive_no_clone(input: proc_macro::TokenStream) -> proc_macro::TokenStrea
|
|||||||
derive_no_clone::derive(input)
|
derive_no_clone::derive(input)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Implements the `ForEachVariant` derive macro which creates a helper for iterating over each
|
||||||
|
/// variant of an enum at compile time. The derive panics if used on non-enum types.
|
||||||
|
///
|
||||||
|
/// The derive creates a macro (hereafter called loop-macro) named `for_each_NAME_variant` where
|
||||||
|
/// `NAME` is replaced with the name of the enum converted to snake case. The loop-macro takes a
|
||||||
|
/// name of another macro (hereafter called iterator-macro) as an argument followed by a
|
||||||
|
/// parenthesized list of extra arguments. The loop-macro expands to a call of the iterator-macro
|
||||||
|
/// with a list of comma-separated names of the enum variants wrapped in square brackets, followed
|
||||||
|
/// by the extra arguments defined above.
|
||||||
|
///
|
||||||
|
/// For example, the following code:
|
||||||
|
/// ```no_compile
|
||||||
|
/// #[derive(ForEachVariant)]
|
||||||
|
/// pub enum FooBar {
|
||||||
|
/// Foo,
|
||||||
|
/// Bar,
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
/// results in the following macro being defined:
|
||||||
|
/// ```
|
||||||
|
/// #[macro_export]
|
||||||
|
/// macro_rules! for_each_foo_bar_variant {
|
||||||
|
/// ( $f:ident($( $args:tt )*) ) => { $f!([Foo, Bar] $($args)*) }
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// pub(crate) use for_each_foo_bar_variant;
|
||||||
|
/// ```
|
||||||
|
#[proc_macro_derive(ForEachVariant)]
|
||||||
|
pub fn derive_for_each_variant(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
||||||
|
derive_for_each_variant::derive(input)
|
||||||
|
}
|
||||||
|
|
||||||
/// Exposes the function as an application entry point. Entry points are alternative application
|
/// Exposes the function as an application entry point. Entry points are alternative application
|
||||||
/// running modes that you can access by adding `?entry=` to the end of the application URL.
|
/// running modes that you can access by adding `?entry=` to the end of the application URL.
|
||||||
#[proc_macro_attribute]
|
#[proc_macro_attribute]
|
||||||
|
Loading…
Reference in New Issue
Block a user