mirror of
https://github.com/enso-org/enso.git
synced 2024-11-25 21:25:20 +03:00
move method icon definition to documentation tag (#7123)
This commit is contained in:
parent
26bd95cf3d
commit
cb9d4c4607
3
Cargo.lock
generated
3
Cargo.lock
generated
@ -1603,8 +1603,11 @@ dependencies = [
|
||||
name = "debug-scene-icons"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"convert_case 0.6.0",
|
||||
"ensogl",
|
||||
"ensogl-hardcoded-theme",
|
||||
"ensogl-text-msdf",
|
||||
"ensogl-tooltip",
|
||||
"ide-view-component-list-panel-grid",
|
||||
"ide-view-component-list-panel-icons",
|
||||
"ide-view-graph-editor",
|
||||
|
@ -80,12 +80,6 @@ pub mod constants {
|
||||
/// The "void" atom returned by function meant to not return any argument.
|
||||
pub const NOTHING: &str = "Nothing";
|
||||
}
|
||||
|
||||
/// The tag name of documentation sections marked as "PRIVATE"
|
||||
pub const PRIVATE_DOC_SECTION_TAG_NAME: &str = "PRIVATE";
|
||||
|
||||
/// The tag name of a documentation section with a method alias.
|
||||
pub const ALIAS_DOC_SECTION_TAG_NAME: &str = "ALIAS";
|
||||
}
|
||||
|
||||
pub use crumbs::Crumb;
|
||||
|
@ -12,6 +12,7 @@ use convert_case::Case;
|
||||
use convert_case::Casing;
|
||||
use double_representation::name::QualifiedName;
|
||||
use enso_doc_parser::DocSection;
|
||||
use enso_doc_parser::Tag;
|
||||
use ordered_float::OrderedFloat;
|
||||
|
||||
|
||||
@ -237,11 +238,10 @@ impl Component {
|
||||
/// Check whether the component contains the "PRIVATE" tag.
|
||||
pub fn is_private(&self) -> bool {
|
||||
match &self.data {
|
||||
Data::FromDatabase { entry, .. } => entry.documentation.iter().any(|doc| match doc {
|
||||
DocSection::Tag { name, .. } =>
|
||||
name == &ast::constants::PRIVATE_DOC_SECTION_TAG_NAME,
|
||||
_ => false,
|
||||
}),
|
||||
Data::FromDatabase { entry, .. } => entry
|
||||
.documentation
|
||||
.iter()
|
||||
.any(|doc| matches!(doc, DocSection::Tag { tag: Tag::Private, .. })),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
@ -252,8 +252,7 @@ impl Component {
|
||||
let aliases = match &self.data {
|
||||
Data::FromDatabase { entry, .. } => {
|
||||
let aliases = entry.documentation.iter().filter_map(|doc| match doc {
|
||||
DocSection::Tag { name, body }
|
||||
if name == &ast::constants::ALIAS_DOC_SECTION_TAG_NAME =>
|
||||
DocSection::Tag { tag: Tag::Alias, body } =>
|
||||
Some(body.as_str().split(',').map(|s| s.trim())),
|
||||
_ => None,
|
||||
});
|
||||
|
@ -627,8 +627,7 @@ mod tests {
|
||||
/// excluded from the list.
|
||||
#[test]
|
||||
fn building_component_list_with_private_component() {
|
||||
use ast::constants::PRIVATE_DOC_SECTION_TAG_NAME as PRIVATE_TAG;
|
||||
let private_doc_section = enso_suggestion_database::doc_section!(@ PRIVATE_TAG, "");
|
||||
let private_doc_section = enso_suggestion_database::doc_section!(@ Private, "");
|
||||
let suggestion_db = enso_suggestion_database::mock_suggestion_database! {
|
||||
test.Test {
|
||||
mod LocalModule {
|
||||
|
@ -723,7 +723,7 @@ impl FilteredDocSections {
|
||||
let mut examples = Vec::new();
|
||||
for section in doc_sections {
|
||||
match section {
|
||||
DocSection::Tag { name, body } => tags.push(Tag::new(name, body)),
|
||||
DocSection::Tag { tag, body } => tags.push(Tag::new(tag.to_str(), body)),
|
||||
DocSection::Marked { mark: Mark::Example, .. } => examples.push(section.clone()),
|
||||
section => synopsis.push(section.clone()),
|
||||
}
|
||||
@ -838,21 +838,21 @@ mod tests {
|
||||
Bar (b);
|
||||
|
||||
#[with_doc_section(doc_section!("Documentation of method A.baz."))]
|
||||
#[with_doc_section(doc_section!(@ "Tag", "Tag body."))]
|
||||
#[with_doc_section(doc_section!(@ Deprecated, "Tag body."))]
|
||||
fn baz() -> Standard.Base.B;
|
||||
}
|
||||
|
||||
#[with_doc_section(doc_section!("Documentation of type B."))]
|
||||
type B {
|
||||
#[with_doc_section(doc_section!("Documentation of constructor B.New."))]
|
||||
#[with_doc_section(doc_section!(@ "AnotherTag", "Tag body."))]
|
||||
#[with_doc_section(doc_section!(@ Alias, "Tag body."))]
|
||||
#[with_doc_section(doc_section!(! "Important", "Important note."))]
|
||||
#[with_doc_section(doc_section!(> "Example", "Example of constructor B.New usage."))]
|
||||
New;
|
||||
}
|
||||
|
||||
#[with_doc_section(doc_section!("Documentation of module method."))]
|
||||
#[with_doc_section(doc_section!(@ "Deprecated", ""))]
|
||||
#[with_doc_section(doc_section!(@ Deprecated, ""))]
|
||||
#[with_doc_section(doc_section!(> "Example", "Example of module method usage."))]
|
||||
fn module_method() -> Standard.Base.A;
|
||||
}
|
||||
@ -875,7 +875,7 @@ mod tests {
|
||||
name: QualifiedName::from_text("Standard.Base.module_method").unwrap().into(),
|
||||
tags: Tags {
|
||||
list: SortedVec::new([Tag {
|
||||
name: "Deprecated".to_im_string(),
|
||||
name: "DEPRECATED".to_im_string(),
|
||||
body: "".to_im_string(),
|
||||
}]),
|
||||
},
|
||||
@ -936,7 +936,7 @@ mod tests {
|
||||
fn a_baz_method() -> Function {
|
||||
Function {
|
||||
name: QualifiedName::from_text("Standard.Base.A.baz").unwrap().into(),
|
||||
tags: Tags { list: vec![Tag::new("Tag", "Tag body.")].into() },
|
||||
tags: Tags { list: vec![Tag::new("DEPRECATED", "Tag body.")].into() },
|
||||
arguments: default(),
|
||||
synopsis: Synopsis::from_doc_sections([doc_section!(
|
||||
"Documentation of method A.baz."
|
||||
@ -960,7 +960,7 @@ mod tests {
|
||||
fn b_new_constructor() -> Function {
|
||||
Function {
|
||||
name: QualifiedName::from_text("Standard.Base.B.New").unwrap().into(),
|
||||
tags: Tags { list: vec![Tag::new("AnotherTag", "Tag body.")].into() },
|
||||
tags: Tags { list: vec![Tag::new("ALIAS", "Tag body.")].into() },
|
||||
arguments: default(),
|
||||
synopsis: Synopsis::from_doc_sections([
|
||||
doc_section!("Documentation of constructor B.New."),
|
||||
|
@ -16,6 +16,7 @@ use engine_protocol::language_server;
|
||||
use engine_protocol::language_server::FieldUpdate;
|
||||
use engine_protocol::language_server::SuggestionsDatabaseModification;
|
||||
use enso_doc_parser::DocSection;
|
||||
use enso_doc_parser::Tag;
|
||||
use enso_text::Location;
|
||||
use language_server::types::FieldAction;
|
||||
|
||||
@ -30,16 +31,6 @@ pub use language_server::types::SuggestionsDatabaseUpdate as Update;
|
||||
|
||||
|
||||
|
||||
// =================
|
||||
// === Constants ===
|
||||
// =================
|
||||
|
||||
/// Key of the keyed [`language_server::types::DocSection`] containing a name of an icon in its
|
||||
/// body.
|
||||
const ICON_DOC_SECTION_KEY: &str = "Icon";
|
||||
|
||||
|
||||
|
||||
// ==============
|
||||
// === Errors ===
|
||||
// ==============
|
||||
@ -91,25 +82,23 @@ pub struct ModuleSpan {
|
||||
// ================
|
||||
|
||||
/// Name of an icon. The name is composed of words with unspecified casing.
|
||||
///
|
||||
/// In order to make icon definitions more readable for non-programmer users, the builtin icon name
|
||||
/// is allowed to be formatted in arbitrary casing. Either `SNAKE_case`,`camelCase`, `Pascal_Case`
|
||||
/// etc. is allowed.
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct IconName {
|
||||
/// Internally the name is kept in PascalCase to optimize converting into
|
||||
/// [`component_group_view::icon::Id`].
|
||||
/// The name is kept in `PascalCase` to allow easy conversion into builtin icon ID.
|
||||
pascal_cased: ImString,
|
||||
}
|
||||
|
||||
impl IconName {
|
||||
/// Construct from a name formatted in snake_case.
|
||||
pub fn from_snake_case(s: impl AsRef<str>) -> Self {
|
||||
let pascal_cased = s.as_ref().from_case(Case::Snake).to_case(Case::Pascal).into();
|
||||
/// Parse arbitrary tag body with any casing into an `PascalCase` icon name.
|
||||
pub fn from_tag_body(s: &str) -> Self {
|
||||
let pascal_cased = s.to_case(Case::Pascal).into();
|
||||
Self { pascal_cased }
|
||||
}
|
||||
|
||||
/// Convert to a name formatted in snake_case.
|
||||
pub fn to_snake_case(&self) -> ImString {
|
||||
self.pascal_cased.from_case(Case::Pascal).to_case(Case::Snake).into()
|
||||
}
|
||||
|
||||
/// Convert to a name formatted in PascalCase.
|
||||
pub fn to_pascal_case(&self) -> ImString {
|
||||
self.pascal_cased.clone()
|
||||
@ -977,19 +966,7 @@ where
|
||||
fn find_icon_name_in_doc_sections<'a, I>(doc_sections: I) -> Option<IconName>
|
||||
where I: IntoIterator<Item = &'a DocSection> {
|
||||
doc_sections.into_iter().find_map(|section| match section {
|
||||
DocSection::Keyed { key, body } if key == ICON_DOC_SECTION_KEY => {
|
||||
let icon_name = IconName::from_snake_case(body);
|
||||
let as_snake_case = icon_name.to_snake_case();
|
||||
if as_snake_case.as_str() != body.as_str() || !body.is_case(Case::Snake) {
|
||||
let msg = format!(
|
||||
"The icon name {body} used in the {ICON_DOC_SECTION_KEY} section of the \
|
||||
documentation of a component is not a valid, losslessly-convertible snake_case \
|
||||
identifier. The component may be displayed with a different icon than expected."
|
||||
);
|
||||
warn!("{msg}");
|
||||
}
|
||||
Some(icon_name)
|
||||
}
|
||||
DocSection::Tag { tag: Tag::Icon, body } => Some(IconName::from_tag_body(body)),
|
||||
_ => None,
|
||||
})
|
||||
}
|
||||
@ -1274,8 +1251,8 @@ mod test {
|
||||
use enso_doc_parser::DocSection;
|
||||
let doc_sections = [
|
||||
DocSection::Paragraph { body: "Some paragraph.".into() },
|
||||
DocSection::Keyed { key: "NotIcon".into(), body: "example_not_icon_body".into() },
|
||||
DocSection::Keyed { key: "Icon".into(), body: "example_icon_name".into() },
|
||||
DocSection::Tag { tag: Tag::Advanced, body: "example_not_icon_body".into() },
|
||||
DocSection::Tag { tag: Tag::Icon, body: "ExampleIconName".into() },
|
||||
DocSection::Paragraph { body: "Another paragraph.".into() },
|
||||
];
|
||||
let icon_name = find_icon_name_in_doc_sections(&doc_sections).unwrap();
|
||||
@ -1286,8 +1263,8 @@ mod test {
|
||||
/// converting [`IconName`] values to PascalCase.
|
||||
#[test]
|
||||
fn icon_name_case_insensitiveness() {
|
||||
let name_from_small_snake_case = IconName::from_snake_case("an_example_name");
|
||||
let name_from_mixed_snake_case = IconName::from_snake_case("aN_EXAMPLE_name");
|
||||
let name_from_small_snake_case = IconName::from_tag_body("an_example_name");
|
||||
let name_from_mixed_snake_case = IconName::from_tag_body("An_EXAMPLE_name");
|
||||
const PASCAL_CASE_NAME: &str = "AnExampleName";
|
||||
assert_eq!(name_from_small_snake_case, name_from_mixed_snake_case);
|
||||
assert_eq!(name_from_small_snake_case.to_pascal_case(), PASCAL_CASE_NAME);
|
||||
|
@ -52,8 +52,7 @@ pub const DEFAULT_TYPE: &str = "Standard.Base.Any";
|
||||
///
|
||||
/// let mut builder = Builder::new();
|
||||
/// builder.add_and_enter_module("local.Project", |e| e);
|
||||
/// builder
|
||||
/// .add_and_enter_type("Type", vec![], |e| e.with_icon(IconName::from_snake_case("an_icon")));
|
||||
/// builder.add_and_enter_type("Type", vec![], |e| e.with_icon(IconName::from_tag_body("an_icon")));
|
||||
/// builder.add_constructor("Constructor", vec![], |e| e);
|
||||
/// builder.leave();
|
||||
/// builder.add_method("module_method", vec![], "local.Project.Type", true, |e| e);
|
||||
@ -320,7 +319,7 @@ macro_rules! mock_suggestion_database_entries {
|
||||
/// static fn static_method(x) -> Standard.Base.Number;
|
||||
/// }
|
||||
///
|
||||
/// #[with_icon(entry::IconName::from_snake_case("TestIcon"))]
|
||||
/// #[with_icon(entry::IconName::from_tag_body("TestIcon"))]
|
||||
/// static fn module_method() -> local.Project.Submodule.TestType;
|
||||
/// }
|
||||
/// }
|
||||
@ -405,7 +404,7 @@ macro_rules! doc_section_mark {
|
||||
/// ### [`DocSection::Tag`]
|
||||
/// ```
|
||||
/// # use enso_suggestion_database::doc_section;
|
||||
/// doc_section!(@ "Tag name", "Tag body.");
|
||||
/// doc_section!(@ Deprecated, "Tag body.");
|
||||
/// ```
|
||||
///
|
||||
/// ### [`DocSection::Keyed`]
|
||||
@ -426,8 +425,11 @@ macro_rules! doc_section_mark {
|
||||
/// ```
|
||||
#[macro_export]
|
||||
macro_rules! doc_section {
|
||||
(@ $tag:expr, $body:expr) => {
|
||||
$crate::mock::enso_doc_parser::DocSection::Tag { name: $tag.into(), body: $body.into() }
|
||||
(@ $tag:ident, $body:expr) => {
|
||||
$crate::mock::enso_doc_parser::DocSection::Tag {
|
||||
tag: $crate::mock::enso_doc_parser::Tag::$tag,
|
||||
body: $body.into(),
|
||||
}
|
||||
};
|
||||
($mark:tt $body:expr) => {
|
||||
$crate::mock::enso_doc_parser::DocSection::Marked {
|
||||
@ -478,7 +480,7 @@ pub fn standard_db_mock() -> SuggestionDatabase {
|
||||
static fn static_method(x) -> Standard.Base.Number;
|
||||
}
|
||||
|
||||
#[with_icon(entry::IconName::from_snake_case("TestIcon"))]
|
||||
#[with_icon(entry::IconName::from_tag_body("TestIcon"))]
|
||||
static fn module_method() -> local.Project.Submodule.TestType;
|
||||
}
|
||||
}
|
||||
|
@ -12,6 +12,7 @@ use ensogl::prelude::*;
|
||||
|
||||
use enso_doc_parser::DocSection;
|
||||
use enso_doc_parser::Mark;
|
||||
use enso_doc_parser::Tag;
|
||||
use enso_suggestion_database as suggestion_database;
|
||||
use enso_suggestion_database::doc_section;
|
||||
use enso_suggestion_database::documentation_ir::EntryDocumentation;
|
||||
@ -94,7 +95,7 @@ fn database() -> SuggestionDatabase {
|
||||
#[with_doc_section(doc_section!(? "Info", "Info sections provide some insights."))]
|
||||
Standard.Base {
|
||||
#[with_doc_section(doc_section!("Maybe type."))]
|
||||
#[with_doc_section(doc_section!(@ "Annotated", ""))]
|
||||
#[with_doc_section(doc_section!(@ Advanced, ""))]
|
||||
type Delimited_Format (a) {
|
||||
#[with_doc_section(doc_section!("Some constructor."))]
|
||||
#[with_doc_section(doc_section!(> "Example", "Some 1"))]
|
||||
@ -135,7 +136,7 @@ fn database() -> SuggestionDatabase {
|
||||
builder.add_function("bar", args, "Standard.Base.Boolean", scope.clone(), |e| {
|
||||
e.with_doc_sections(vec![
|
||||
DocSection::Paragraph { body: "Documentation for the bar function.".into() },
|
||||
DocSection::Tag { name: "DEPRECATED", body: default() },
|
||||
DocSection::Tag { tag: Tag::Deprecated, body: default() },
|
||||
DocSection::Marked {
|
||||
mark: Mark::Example,
|
||||
header: None,
|
||||
@ -147,7 +148,7 @@ fn database() -> SuggestionDatabase {
|
||||
builder.add_local("local1", "Standard.Base.Boolean", scope, |e| {
|
||||
e.with_doc_sections(vec![
|
||||
DocSection::Paragraph { body: "Documentation for the local1 variable.".into() },
|
||||
DocSection::Tag { name: "SOMETAG", body: default() },
|
||||
DocSection::Tag { tag: Tag::Advanced, body: default() },
|
||||
])
|
||||
});
|
||||
|
||||
|
@ -8,8 +8,11 @@ edition = "2021"
|
||||
crate-type = ["cdylib", "rlib"]
|
||||
|
||||
[dependencies]
|
||||
convert_case = { workspace = true }
|
||||
ensogl = { path = "../../../../../lib/rust/ensogl" }
|
||||
ensogl-hardcoded-theme = { path = "../../../../../lib/rust/ensogl/app/theme/hardcoded" }
|
||||
ensogl-text-msdf = { path = "../../../../../lib/rust/ensogl/component/text/src/font/msdf" }
|
||||
ensogl-tooltip = { path = "../../../../../lib/rust/ensogl/component/tooltip/" }
|
||||
ide-view-component-list-panel-grid = { path = "../../component-browser/component-list-panel/grid" }
|
||||
ide-view-component-list-panel-icons = { path = "../../component-browser/component-list-panel/icons" }
|
||||
ide-view-graph-editor = { path = "../../graph-editor" }
|
||||
|
@ -8,13 +8,19 @@ use ensogl::system::web::traits::*;
|
||||
use ide_view_component_list_panel_grid::prelude::*;
|
||||
use wasm_bindgen::prelude::*;
|
||||
|
||||
use convert_case::Case;
|
||||
use convert_case::Casing;
|
||||
use ensogl::application::Application;
|
||||
use ensogl::control::io::mouse;
|
||||
use ensogl::data::color;
|
||||
use ensogl::display::navigation::navigator::Navigator;
|
||||
use ensogl::display::object::Object;
|
||||
use ensogl::display::shape::Rectangle;
|
||||
use ensogl::display::world::World;
|
||||
use ensogl::display::DomSymbol;
|
||||
use ensogl::system::web;
|
||||
use ensogl_text_msdf::run_once_initialized;
|
||||
use ensogl_tooltip::Tooltip;
|
||||
use ide_view_component_list_panel_grid::entry::icon;
|
||||
use ide_view_component_list_panel_icons::SHRINK_AMOUNT;
|
||||
use ide_view_component_list_panel_icons::SIZE;
|
||||
@ -52,9 +58,15 @@ mod frame {
|
||||
#[wasm_bindgen]
|
||||
#[allow(dead_code)]
|
||||
pub fn entry_point_icons() {
|
||||
run_once_initialized(init);
|
||||
}
|
||||
|
||||
fn init() {
|
||||
let app = Application::new("root");
|
||||
let tooltip = Tooltip::new(&app);
|
||||
let network = app.frp.network();
|
||||
|
||||
let world = app.display.clone();
|
||||
mem::forget(app);
|
||||
let scene = &world.default_scene;
|
||||
mem::forget(Navigator::new(scene, &scene.camera()));
|
||||
|
||||
@ -68,10 +80,25 @@ pub fn entry_point_icons() {
|
||||
let shape = ide_view_component_list_panel_icons::any::View::new();
|
||||
shape.icon.set(id.any_cached_shape_location());
|
||||
shape.r_component.set(dark_green.into());
|
||||
place_icon(&world, shape, x, 0.0);
|
||||
let hover_target = place_icon(&world, shape, x, 0.0);
|
||||
x += 20.0;
|
||||
|
||||
let enter = hover_target.on_event::<mouse::Enter>();
|
||||
let leave = hover_target.on_event::<mouse::Leave>();
|
||||
let snake_case_name = id.as_str().to_case(Case::Snake);
|
||||
let style = ensogl::application::tooltip::Style::set_label(snake_case_name);
|
||||
frp::extend! { network
|
||||
trace enter;
|
||||
trace leave;
|
||||
tooltip.frp.set_style <+ enter.constant(style);
|
||||
tooltip.frp.set_style <+ leave.constant(default());
|
||||
}
|
||||
mem::forget(hover_target);
|
||||
});
|
||||
|
||||
scene.add_child(&tooltip);
|
||||
mem::forget(tooltip);
|
||||
|
||||
|
||||
// === Action Bar Icons ===
|
||||
|
||||
@ -101,6 +128,8 @@ pub fn entry_point_icons() {
|
||||
let enable_output_context_icon = action_bar::icon::enable_output_context::View::new();
|
||||
enable_output_context_icon.color_rgba.set(dark_green.into());
|
||||
place_icon(&world, enable_output_context_icon, 60.0, y);
|
||||
|
||||
mem::forget(app);
|
||||
}
|
||||
|
||||
/// Create a grid with pixel squares to help development of icons.
|
||||
@ -124,9 +153,15 @@ fn create_grid(world: &World, x: f32, y: f32) {
|
||||
}
|
||||
|
||||
/// Place the given icon in the world at the right coordinates, in a dark green shade.
|
||||
fn place_icon(world: &World, icon: impl Object, x: f32, y: f32) {
|
||||
fn place_icon(world: &World, icon: impl Object, x: f32, y: f32) -> Rectangle {
|
||||
let hover_target = Rectangle();
|
||||
hover_target.set_color(ensogl::display::shape::INVISIBLE_HOVER_COLOR);
|
||||
hover_target.set_xy((x - SIZE / 2.0, y - SIZE / 2.0));
|
||||
hover_target.set_size((SIZE, SIZE));
|
||||
icon.set_xy((x, y));
|
||||
icon.set_size((SIZE, SIZE));
|
||||
world.add_child(&hover_target);
|
||||
world.add_child(&icon);
|
||||
mem::forget(icon);
|
||||
hover_target
|
||||
}
|
||||
|
@ -137,7 +137,8 @@ type Table
|
||||
column_count : Integer
|
||||
column_count self = self.internal_columns.length
|
||||
|
||||
## Returns a new table with a chosen subset of columns, as specified by the
|
||||
## ICON select_column
|
||||
Returns a new table with a chosen subset of columns, as specified by the
|
||||
`columns`, from the input table. Any unmatched input columns will be
|
||||
dropped from the output.
|
||||
|
||||
@ -183,8 +184,6 @@ type Table
|
||||
Select the first two columns and the last column, moving the last one to front.
|
||||
|
||||
table.select_columns [-1, 0, 1] reorder=True
|
||||
|
||||
Icon: select_column
|
||||
@columns Widget_Helpers.make_column_name_vector_selector
|
||||
select_columns : Vector (Integer | Text | Column_Selector) | Text | Integer -> Boolean -> Boolean -> Problem_Behavior -> Table ! No_Output_Columns | Missing_Input_Columns
|
||||
select_columns self (columns = [self.columns.first.name]) (reorder = False) (error_on_missing_columns = True) (on_problems = Report_Warning) =
|
||||
|
@ -262,7 +262,8 @@ type Table
|
||||
column_count : Integer
|
||||
column_count self = self.java_table.getColumns.length
|
||||
|
||||
## Returns a new table with a chosen subset of columns, as specified by the
|
||||
## ICON select_column
|
||||
Returns a new table with a chosen subset of columns, as specified by the
|
||||
`columns`, from the input table. Any unmatched input columns will be
|
||||
dropped from the output.
|
||||
|
||||
@ -309,8 +310,6 @@ type Table
|
||||
Select the first two columns and the last column, moving the last one to front.
|
||||
|
||||
table.select_columns [-1, 0, 1] reorder=True
|
||||
|
||||
Icon: select_column
|
||||
@columns Widget_Helpers.make_column_name_vector_selector
|
||||
select_columns : Vector (Integer | Text | Column_Selector) | Text | Integer -> Boolean -> Boolean -> Problem_Behavior -> Table ! No_Output_Columns | Missing_Input_Columns
|
||||
select_columns self columns=[self.columns.first.name] (reorder = False) (error_on_missing_columns = True) (on_problems = Report_Warning) =
|
||||
|
@ -69,7 +69,7 @@ pub enum DocSection {
|
||||
/// The documentation tag.
|
||||
Tag {
|
||||
/// The tag name.
|
||||
name: &'static str,
|
||||
tag: Tag,
|
||||
/// The tag text.
|
||||
body: HtmlString,
|
||||
},
|
||||
@ -141,9 +141,8 @@ impl DocSectionCollector {
|
||||
|
||||
impl<L> TokenConsumer<L> for DocSectionCollector {
|
||||
fn tag(&mut self, tag: Tag, description: Option<Span<'_, L>>) {
|
||||
let name = tag.to_str();
|
||||
let body = description.map(|description| description.to_string()).unwrap_or_default();
|
||||
self.sections.push(DocSection::Tag { name, body });
|
||||
self.sections.push(DocSection::Tag { tag, body });
|
||||
}
|
||||
|
||||
fn enter_marked_section(&mut self, mark: Mark, header: Option<Span<'_, L>>) {
|
||||
|
@ -55,13 +55,14 @@ pub struct TagWithDescription<'a, L> {
|
||||
}
|
||||
|
||||
/// Indicator placed at the beginning of a documentation section, e.g. `PRIVATE`.
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
#[derive(Hash, Debug, Clone, Copy, PartialEq, Eq)]
|
||||
#[allow(missing_docs)]
|
||||
pub enum Tag {
|
||||
Added,
|
||||
Advanced,
|
||||
Alias,
|
||||
Deprecated,
|
||||
Icon,
|
||||
Modified,
|
||||
Private,
|
||||
Removed,
|
||||
@ -90,6 +91,7 @@ impl Tag {
|
||||
"ADVANCED" => Some(Advanced),
|
||||
"ALIAS" => Some(Alias),
|
||||
"DEPRECATED" => Some(Deprecated),
|
||||
"ICON" => Some(Icon),
|
||||
"MODIFIED" => Some(Modified),
|
||||
"PRIVATE" => Some(Private),
|
||||
"REMOVED" => Some(Removed),
|
||||
@ -107,6 +109,7 @@ impl Tag {
|
||||
Tag::Advanced => "ADVANCED",
|
||||
Tag::Alias => "ALIAS",
|
||||
Tag::Deprecated => "DEPRECATED",
|
||||
Tag::Icon => "ICON",
|
||||
Tag::Modified => "MODIFIED",
|
||||
Tag::Private => "PRIVATE",
|
||||
Tag::Removed => "REMOVED",
|
||||
|
Loading…
Reference in New Issue
Block a user