tabular_data_preview: Finish generalizing crate naming (#62807)
# Objective #62768 renamed `crates/csv_preview` to `crates/tabular_data_preview`, but left the CSV-specific names inside it untouched (on purpose, to reduce prev PR scope & git diff noise) ## Solution Finished the generalization, one mechanical rename per commit for easier review: 1. `CsvPreviewView` -> `TabularDataPreviewPane` 2. `CsvPreviewSettings` -> `TabularDataPreviewSettings` 3. Methods/vars 4. Test helpers/fn names 5. User-facing strings and element ids: tab title fallback: - `"CSV Preview"` -> `"Tabular Data Preview"`, - empty state `"No CSV content to display"` -> `"No data to display"`, - dev tooltip, and element ids `csv-filter-*`/`csv-col-header-*`/`csv-table`/`csv-display-cell-*` -> `table-*`/`tabular-data-table` 6. Doc comments that implied CSV-only behavior, reworded to be format-agnostic > NOTE: PR is split into commits by change type for ease of review) ## Testing `cargo check -p tabular_data_preview -p zed` builds clean after each commit; `cargo test -p tabular_data_preview --lib` passes (10/10). ## Self-Review Checklist: - [x] I've reviewed my own diff for quality, security, and reliability - [ ] Unsafe blocks (if any) have justifying comments - [x] The content adheres to Zed's UI standards ([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist) and [icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md) guidelines) - [x] Tests cover the new/changed behavior - [x] Performance impact has been considered and is acceptable Release Notes: - N/A
This commit is contained in:
1 parent
d0394b7c8c
commit
4aef01479b
16 files changed
+116
-110
No files matched your search
@@ -1,7 +1,7 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::{
|
||||
CsvPreviewView,
|
||||
TabularDataPreviewPane,
|
||||
types::TableLikeContent,
|
||||
types::{LineNumber, TableCell},
|
||||
};
|
||||
@@ -52,18 +52,18 @@ impl TabularFormat {
|
||||
}
|
||||
}
|
||||
|
||||
impl CsvPreviewView {
|
||||
pub(crate) fn parse_csv_from_active_editor(
|
||||
impl TabularDataPreviewPane {
|
||||
pub(crate) fn parse_from_active_editor(
|
||||
&mut self,
|
||||
wait_for_debounce: bool,
|
||||
cx: &mut Context<Self>,
|
||||
) {
|
||||
let editor = self.active_editor_state.editor.clone();
|
||||
self.is_parsing = true;
|
||||
self.parsing_task = Some(self.parse_csv_in_background(wait_for_debounce, editor, cx));
|
||||
self.parsing_task = Some(self.parse_in_background(wait_for_debounce, editor, cx));
|
||||
}
|
||||
|
||||
fn parse_csv_in_background(
|
||||
fn parse_in_background(
|
||||
&mut self,
|
||||
wait_for_debounce: bool,
|
||||
editor: Entity<Editor>,
|
||||
@@ -127,19 +127,19 @@ impl CsvPreviewView {
|
||||
};
|
||||
|
||||
let instant = Instant::now();
|
||||
let parsed_csv = cx
|
||||
let parsed_contents = cx
|
||||
.background_spawn(async move { from_buffer_with_delimiter(&buffer_snapshot, delimiter) })
|
||||
.await;
|
||||
let parse_duration = instant.elapsed();
|
||||
let parse_end_time: Instant = Instant::now();
|
||||
log::debug!("Parsed CSV in {}ms", parse_duration.as_millis());
|
||||
log::debug!("Parsed data in {}ms", parse_duration.as_millis());
|
||||
view.update(cx, move |view, cx| {
|
||||
view.performance_metrics
|
||||
.timings
|
||||
.insert("Parsing", (parse_duration, Instant::now()));
|
||||
|
||||
log::debug!("Parsed {} rows", parsed_csv.rows.len());
|
||||
view.engine.contents = Arc::new(parsed_csv);
|
||||
log::debug!("Parsed {} rows", parsed_contents.rows.len());
|
||||
view.engine.contents = Arc::new(parsed_contents);
|
||||
view.engine.calculate_available_filters();
|
||||
view.sync_column_widths(cx);
|
||||
view.last_parse_end_time = Some(parse_end_time);
|
||||
@@ -162,13 +162,14 @@ pub fn from_buffer_with_delimiter(
|
||||
return TableLikeContent::default();
|
||||
}
|
||||
|
||||
let (parsed_cells_with_positions, line_numbers) = parse_csv_with_positions(&text, delimiter);
|
||||
let (parsed_cells_with_positions, line_numbers) =
|
||||
parse_delimited_text_with_positions(&text, delimiter);
|
||||
if parsed_cells_with_positions.is_empty() {
|
||||
return TableLikeContent::default();
|
||||
}
|
||||
let raw_headers = parsed_cells_with_positions[0].clone();
|
||||
|
||||
// Calculating the longest row, as CSV might have less headers than max row width
|
||||
// Calculating the longest row, as the data might have fewer headers than max row width
|
||||
let Some(max_number_of_cols) = parsed_cells_with_positions.iter().map(|r| r.len()).max() else {
|
||||
return TableLikeContent::default();
|
||||
};
|
||||
@@ -192,8 +193,8 @@ pub fn from_buffer_with_delimiter(
|
||||
}
|
||||
}
|
||||
|
||||
/// Parse CSV and track byte positions for each cell
|
||||
fn parse_csv_with_positions(
|
||||
/// Parse delimited text and track byte positions for each cell
|
||||
fn parse_delimited_text_with_positions(
|
||||
text: &str,
|
||||
delimiter: char,
|
||||
) -> (
|
||||
@@ -477,7 +478,7 @@ Jane,"Simple name""#;
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_empty_csv() {
|
||||
fn test_empty_input() {
|
||||
let parsed = TableLikeContent::from_str("".to_string());
|
||||
assert_eq!(parsed.headers.cols(), 0);
|
||||
assert!(parsed.rows.is_empty());
|
||||
@@ -486,7 +487,7 @@ Jane,"Simple name""#;
|
||||
#[test]
|
||||
fn test_tsv_parsing() {
|
||||
let tsv_data = "Name\tAge\tCity\nJohn\t30\tNew York\nJane\t25\tLos Angeles";
|
||||
let (parsed_cells, _) = parse_csv_with_positions(tsv_data, '\t');
|
||||
let (parsed_cells, _) = parse_delimited_text_with_positions(tsv_data, '\t');
|
||||
|
||||
assert_eq!(parsed_cells.len(), 3);
|
||||
assert_eq!(parsed_cells[0].len(), 3);
|
||||
@@ -500,7 +501,7 @@ Jane,"Simple name""#;
|
||||
#[test]
|
||||
fn test_psv_parsing() {
|
||||
let psv_data = "Name|Age|City\nJohn|30|New York\nJane|25|Los Angeles";
|
||||
let (parsed_cells, _) = parse_csv_with_positions(psv_data, '|');
|
||||
let (parsed_cells, _) = parse_delimited_text_with_positions(psv_data, '|');
|
||||
|
||||
assert_eq!(parsed_cells.len(), 3);
|
||||
assert_eq!(parsed_cells[0].len(), 3);
|
||||
@@ -514,7 +515,7 @@ Jane,"Simple name""#;
|
||||
#[test]
|
||||
fn test_ssv_parsing() {
|
||||
let ssv_data = "Name;Age;City\nJohn;30;New York\nJane;25;Los Angeles";
|
||||
let (parsed_cells, _) = parse_csv_with_positions(ssv_data, ';');
|
||||
let (parsed_cells, _) = parse_delimited_text_with_positions(ssv_data, ';');
|
||||
|
||||
assert_eq!(parsed_cells.len(), 3);
|
||||
assert_eq!(parsed_cells[0].len(), 3);
|
||||
@@ -528,7 +529,7 @@ Jane,"Simple name""#;
|
||||
#[test]
|
||||
fn test_csv_parsing_quote_offset_handling() {
|
||||
let csv_data = r#"first,"se,cond",third"#;
|
||||
let (parsed_cells, _) = parse_csv_with_positions(csv_data, ',');
|
||||
let (parsed_cells, _) = parse_delimited_text_with_positions(csv_data, ',');
|
||||
|
||||
assert_eq!(parsed_cells.len(), 1); // One row
|
||||
assert_eq!(parsed_cells[0].len(), 3); // Three cells
|
||||
@@ -554,7 +555,7 @@ Jane,"Simple name""#;
|
||||
let csv_data = r#"id,"name with spaces","description, with commas",status
|
||||
1,"John Doe","A person with ""quotes"" and, commas",active
|
||||
2,"Jane Smith","Simple description",inactive"#;
|
||||
let (parsed_cells, _) = parse_csv_with_positions(csv_data, ',');
|
||||
let (parsed_cells, _) = parse_delimited_text_with_positions(csv_data, ',');
|
||||
|
||||
assert_eq!(parsed_cells.len(), 3); // header + 2 rows
|
||||
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
//! Performance metrics overlay for CSV preview debugging.
|
||||
//! Performance metrics overlay for tabular data preview debugging.
|
||||
//!
|
||||
//! Provides a semi-transparent overlay in the bottom-right corner showing
|
||||
//! CSV parsing performance metrics for developer experience.
|
||||
//! Parsing performance metrics for developer experience.
|
||||
|
||||
use ui::{ActiveTheme, Context, IntoElement, ParentElement, Styled, StyledTypography, div};
|
||||
|
||||
use crate::{CsvPreviewView, PerformanceMetrics};
|
||||
use crate::{PerformanceMetrics, TabularDataPreviewPane};
|
||||
|
||||
impl CsvPreviewView {
|
||||
impl TabularDataPreviewPane {
|
||||
/// Renders a semi-transparent performance metrics overlay in the bottom-right corner.
|
||||
///
|
||||
/// Shows CSV parsing duration for debugging and performance monitoring.
|
||||
/// Shows parsing duration for debugging and performance monitoring.
|
||||
/// The overlay is positioned absolutely and styled with reduced opacity.
|
||||
pub(crate) fn render_performance_metrics_overlay(
|
||||
&mut self,
|
||||
|
||||
@@ -2,9 +2,9 @@ use std::time::Instant;
|
||||
|
||||
use ui::{SpinnerLabel, div, prelude::*};
|
||||
|
||||
use crate::CsvPreviewView;
|
||||
use crate::TabularDataPreviewPane;
|
||||
|
||||
impl Render for CsvPreviewView {
|
||||
impl Render for TabularDataPreviewPane {
|
||||
fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
||||
let theme = cx.theme();
|
||||
let row_height = window.pixel_snap(window.line_height());
|
||||
@@ -41,7 +41,7 @@ impl Render for CsvPreviewView {
|
||||
.child("Loading…"),
|
||||
)
|
||||
})
|
||||
.when(!is_parsing, |div| div.child("No CSV content to display"))
|
||||
.when(!is_parsing, |div| div.child("No data to display"))
|
||||
.into_any_element()
|
||||
} else {
|
||||
self.create_table(&self.column_widths.widths, cx)
|
||||
|
||||
@@ -4,12 +4,12 @@ use std::ops::Range;
|
||||
use ui::{ColumnWidthConfig, ResizableColumnsState, Table, UncheckedTableRow, div, prelude::*};
|
||||
|
||||
use crate::{
|
||||
CsvPreviewView,
|
||||
TabularDataPreviewPane,
|
||||
settings::RowRenderMechanism,
|
||||
types::{AnyColumn, DisplayCellId, DisplayRow},
|
||||
};
|
||||
|
||||
impl CsvPreviewView {
|
||||
impl TabularDataPreviewPane {
|
||||
/// Creates a new table.
|
||||
/// Column number is derived from the `ResizableColumnsState` entity.
|
||||
pub(crate) fn create_table(
|
||||
@@ -32,7 +32,7 @@ impl CsvPreviewView {
|
||||
|
||||
headers.push(self.create_row_identifier_header(cx));
|
||||
|
||||
// Add the actual CSV headers with sort buttons
|
||||
// Add the actual data headers with sort buttons
|
||||
for i in 0..(cols - 1) {
|
||||
let header_text = self
|
||||
.engine
|
||||
@@ -77,7 +77,7 @@ impl CsvPreviewView {
|
||||
})
|
||||
}
|
||||
RowRenderMechanism::UniformList => {
|
||||
table.uniform_list("csv-table", row_count, {
|
||||
table.uniform_list("tabular-data-table", row_count, {
|
||||
cx.processor(move |this, range: Range<usize>, _window, cx| {
|
||||
// Record all display indices in the range for performance metrics
|
||||
this.performance_metrics
|
||||
@@ -109,12 +109,12 @@ impl CsvPreviewView {
|
||||
///
|
||||
/// Used both by UniformList and VariableRowHeightList
|
||||
fn render_single_table_row(
|
||||
this: &CsvPreviewView,
|
||||
this: &TabularDataPreviewPane,
|
||||
cols: usize,
|
||||
display_row: DisplayRow,
|
||||
row_identifier_text_color: gpui::Hsla,
|
||||
row_height: Pixels,
|
||||
cx: &Context<CsvPreviewView>,
|
||||
cx: &Context<TabularDataPreviewPane>,
|
||||
) -> Option<UncheckedTableRow<AnyElement>> {
|
||||
// Get the actual row index from our sorted indices
|
||||
let data_row = this.engine.d2d_mapping().get_data_row(display_row)?;
|
||||
@@ -123,7 +123,7 @@ impl CsvPreviewView {
|
||||
let mut elements = Vec::with_capacity(cols);
|
||||
elements.push(this.create_row_identifier_cell(display_row, data_row, cx)?);
|
||||
|
||||
// Remaining columns: actual CSV data
|
||||
// Remaining columns: actual table data
|
||||
for col in (0..this.engine.contents.number_of_cols).map(AnyColumn) {
|
||||
let table_cell = row.expect_get(col);
|
||||
|
||||
@@ -143,7 +143,7 @@ impl CsvPreviewView {
|
||||
.overflow_hidden()
|
||||
},
|
||||
)
|
||||
.child(CsvPreviewView::create_selectable_cell(
|
||||
.child(TabularDataPreviewPane::create_selectable_cell(
|
||||
display_cell_id,
|
||||
cell_content,
|
||||
this.settings.vertical_alignment,
|
||||
|
||||
@@ -5,7 +5,7 @@ use ui::{
|
||||
};
|
||||
|
||||
use crate::{
|
||||
CsvPreviewView,
|
||||
TabularDataPreviewPane,
|
||||
settings::RowIdentifiers,
|
||||
types::{DataRow, DisplayRow, LineNumber},
|
||||
};
|
||||
@@ -45,7 +45,7 @@ impl LineNumber {
|
||||
}
|
||||
}
|
||||
|
||||
impl CsvPreviewView {
|
||||
impl TabularDataPreviewPane {
|
||||
/// Calculate the optimal width for the row identifier column (line numbers or row numbers).
|
||||
///
|
||||
/// This ensures the column is wide enough to display the largest identifier comfortably,
|
||||
@@ -104,7 +104,7 @@ impl CsvPreviewView {
|
||||
|
||||
pub(crate) fn create_row_identifier_header(
|
||||
&self,
|
||||
cx: &mut Context<'_, CsvPreviewView>,
|
||||
cx: &mut Context<'_, TabularDataPreviewPane>,
|
||||
) -> AnyElement {
|
||||
// First column: row identifier (clickable to toggle between Lines and Rows)
|
||||
let row_identifier_text = match self.settings.numbering_type {
|
||||
@@ -144,7 +144,7 @@ impl CsvPreviewView {
|
||||
&self,
|
||||
display_row: DisplayRow,
|
||||
data_row: DataRow,
|
||||
cx: &Context<'_, CsvPreviewView>,
|
||||
cx: &Context<'_, TabularDataPreviewPane>,
|
||||
) -> Option<AnyElement> {
|
||||
let row_identifier: SharedString = match self.settings.numbering_type {
|
||||
RowIdentifiers::SrcLines => self
|
||||
|
||||
@@ -5,12 +5,12 @@ use ui::{
|
||||
};
|
||||
|
||||
use crate::{
|
||||
CsvPreviewView,
|
||||
TabularDataPreviewPane,
|
||||
settings::{FilterSortOrder, VerticalAlignment},
|
||||
};
|
||||
|
||||
///// Settings related /////
|
||||
impl CsvPreviewView {
|
||||
impl TabularDataPreviewPane {
|
||||
/// Render settings panel above the table
|
||||
pub(crate) fn render_settings_panel(
|
||||
&self,
|
||||
@@ -166,7 +166,7 @@ impl CsvPreviewView {
|
||||
|
||||
#[cfg(feature = "dev-tools")]
|
||||
fn create_dev_only_popover_menu(
|
||||
cx: &mut Context<'_, CsvPreviewView>,
|
||||
cx: &mut Context<'_, TabularDataPreviewPane>,
|
||||
) -> ui::PopoverMenu<ContextMenu> {
|
||||
use crate::settings::RowRenderMechanism;
|
||||
use ui::{IconButton, IconName, IconPosition, IconSize, PopoverMenu};
|
||||
@@ -175,7 +175,7 @@ fn create_dev_only_popover_menu(
|
||||
.trigger_with_tooltip(
|
||||
IconButton::new("debug-options-trigger", IconName::Settings).icon_size(IconSize::Small),
|
||||
Tooltip::text(
|
||||
"Dev-only section used for debugging purposes.\nWill be removed on public release of CSV feature"
|
||||
"Dev-only section used for debugging purposes.\nWill be removed on public release of the tabular data preview feature"
|
||||
),
|
||||
)
|
||||
.menu({
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
use gpui::{AnyElement, ClipboardItem, ElementId, MouseButton, StatefulInteractiveElement};
|
||||
use ui::{Color, Divider, Label, LabelSize, SharedString, Tooltip, div, prelude::*};
|
||||
|
||||
use crate::{CsvPreviewView, settings::VerticalAlignment, types::DisplayCellId};
|
||||
use crate::{TabularDataPreviewPane, settings::VerticalAlignment, types::DisplayCellId};
|
||||
|
||||
/// Adds a right-click-to-copy handler and a tooltip showing `text` plus `hint`
|
||||
/// (e.g. "Right click to copy content") to a `Stateful` element.
|
||||
@@ -30,13 +30,13 @@ pub(crate) fn with_copy_on_right_click<E: StatefulInteractiveElement>(
|
||||
}))
|
||||
}
|
||||
|
||||
impl CsvPreviewView {
|
||||
impl TabularDataPreviewPane {
|
||||
/// Create selectable table cell with mouse event handlers.
|
||||
pub fn create_selectable_cell(
|
||||
display_cell_id: DisplayCellId,
|
||||
cell_content: SharedString,
|
||||
vertical_alignment: VerticalAlignment,
|
||||
cx: &Context<CsvPreviewView>,
|
||||
cx: &Context<TabularDataPreviewPane>,
|
||||
) -> AnyElement {
|
||||
create_table_cell(display_cell_id, cell_content, vertical_alignment, cx)
|
||||
// Mouse events handlers will be here
|
||||
@@ -49,11 +49,11 @@ fn create_table_cell(
|
||||
display_cell_id: DisplayCellId,
|
||||
cell_content: SharedString,
|
||||
vertical_alignment: VerticalAlignment,
|
||||
cx: &Context<'_, CsvPreviewView>,
|
||||
cx: &Context<'_, TabularDataPreviewPane>,
|
||||
) -> gpui::Stateful<Div> {
|
||||
let cell = div()
|
||||
.id(ElementId::NamedInteger(
|
||||
format!("csv-display-cell-{}", *display_cell_id.row).into(),
|
||||
format!("table-display-cell-{}", *display_cell_id.row).into(),
|
||||
*display_cell_id.col as u64,
|
||||
))
|
||||
.flex()
|
||||
|
||||
@@ -17,7 +17,7 @@ use ui::{
|
||||
};
|
||||
|
||||
use crate::{
|
||||
CsvPreviewView,
|
||||
TabularDataPreviewPane,
|
||||
renderer::table_cell::with_copy_on_right_click,
|
||||
settings::FilterSortOrder,
|
||||
table_data_engine::{
|
||||
@@ -45,7 +45,7 @@ enum ColumnFilterListEntry {
|
||||
|
||||
struct ColumnFilterDelegate {
|
||||
col: AnyColumn,
|
||||
view: Entity<CsvPreviewView>,
|
||||
view: Entity<TabularDataPreviewPane>,
|
||||
/// Row order frozen at open time (available entries sorted per the
|
||||
/// column's `FilterSortOrder`, then entries hidden by other columns'
|
||||
/// filters). Kept stable so toggling a value doesn't reshuffle the list
|
||||
@@ -66,7 +66,7 @@ struct ColumnFilterDelegate {
|
||||
impl ColumnFilterDelegate {
|
||||
fn new(
|
||||
col: AnyColumn,
|
||||
view: Entity<CsvPreviewView>,
|
||||
view: Entity<TabularDataPreviewPane>,
|
||||
sort_order: FilterSortOrder,
|
||||
column_filters: Arc<Vec<(FilterEntry, FilterEntryState)>>,
|
||||
cx: &mut Context<Picker<Self>>,
|
||||
@@ -270,7 +270,7 @@ impl PickerDelegate for ColumnFilterDelegate {
|
||||
type ListItem = AnyElement;
|
||||
|
||||
fn name() -> &'static str {
|
||||
"csv column filter"
|
||||
"table column filter"
|
||||
}
|
||||
|
||||
fn match_count(&self) -> usize {
|
||||
@@ -432,7 +432,7 @@ impl PickerDelegate for ColumnFilterDelegate {
|
||||
};
|
||||
|
||||
Some(
|
||||
ListItem::new(("csv-filter-value", ix))
|
||||
ListItem::new(("table-filter-value", ix))
|
||||
.disabled(is_hidden && !row.is_applied)
|
||||
.inset(true)
|
||||
.spacing(ListItemSpacing::Sparse)
|
||||
@@ -496,7 +496,7 @@ impl PickerDelegate for ColumnFilterDelegate {
|
||||
)
|
||||
.child(
|
||||
div()
|
||||
.id("csv-filter-clear-all")
|
||||
.id("table-filter-clear-all")
|
||||
.cursor_pointer()
|
||||
.child(
|
||||
Label::new("Clear all")
|
||||
@@ -518,12 +518,12 @@ impl PickerDelegate for ColumnFilterDelegate {
|
||||
}
|
||||
}
|
||||
|
||||
impl CsvPreviewView {
|
||||
impl TabularDataPreviewPane {
|
||||
/// Create header for data, which is orderable with text on the left and sort button on the right
|
||||
pub(crate) fn create_header_element_with_sort_button(
|
||||
&self,
|
||||
header_text: SharedString,
|
||||
cx: &mut Context<'_, CsvPreviewView>,
|
||||
cx: &mut Context<'_, TabularDataPreviewPane>,
|
||||
col_idx: AnyColumn,
|
||||
) -> AnyElement {
|
||||
let has_active_filter = self.engine.has_active_filters(col_idx);
|
||||
@@ -532,7 +532,7 @@ impl CsvPreviewView {
|
||||
.applied_sorting
|
||||
.is_some_and(|o| o.col_idx == col_idx);
|
||||
let always_show_buttons = has_active_filter || has_active_sort;
|
||||
let group_name = SharedString::from(format!("csv-col-header-{}", col_idx.get()));
|
||||
let group_name = SharedString::from(format!("table-col-header-{}", col_idx.get()));
|
||||
|
||||
let colors = cx.theme().colors();
|
||||
let base_bg = colors.editor_background;
|
||||
@@ -553,7 +553,7 @@ impl CsvPreviewView {
|
||||
.child({
|
||||
let header_text_cell = div()
|
||||
.id(ElementId::NamedInteger(
|
||||
"csv-col-header-text".into(),
|
||||
"table-col-header-text".into(),
|
||||
col_idx.get() as u64,
|
||||
))
|
||||
.flex_1()
|
||||
@@ -594,7 +594,7 @@ impl CsvPreviewView {
|
||||
|
||||
fn create_sort_button(
|
||||
&self,
|
||||
cx: &mut Context<'_, CsvPreviewView>,
|
||||
cx: &mut Context<'_, TabularDataPreviewPane>,
|
||||
col_idx: AnyColumn,
|
||||
) -> Button {
|
||||
Button::new(
|
||||
@@ -648,7 +648,7 @@ impl CsvPreviewView {
|
||||
|
||||
fn create_filter_button(
|
||||
&self,
|
||||
cx: &mut Context<'_, CsvPreviewView>,
|
||||
cx: &mut Context<'_, TabularDataPreviewPane>,
|
||||
col: AnyColumn,
|
||||
) -> PopoverMenu<Picker<ColumnFilterDelegate>> {
|
||||
let has_active_filters = self.engine.has_active_filters(col);
|
||||
|
||||
@@ -19,7 +19,7 @@ pub enum VerticalAlignment {
|
||||
|
||||
#[derive(Default, Clone, Copy)]
|
||||
pub enum RowIdentifiers {
|
||||
/// Show original line numbers from CSV file
|
||||
/// Show original line numbers from the source file
|
||||
#[default]
|
||||
SrcLines,
|
||||
/// Show sequential row numbers starting from 1
|
||||
@@ -36,7 +36,7 @@ pub enum FilterSortOrder {
|
||||
}
|
||||
|
||||
#[derive(Clone, Default)]
|
||||
pub(crate) struct CsvPreviewSettings {
|
||||
pub(crate) struct TabularDataPreviewSettings {
|
||||
pub(crate) rendering_with: RowRenderMechanism,
|
||||
pub(crate) vertical_alignment: VerticalAlignment,
|
||||
pub(crate) numbering_type: RowIdentifiers,
|
||||
@@ -47,7 +47,7 @@ pub(crate) struct CsvPreviewSettings {
|
||||
pub(crate) multiline_cells_enabled: bool,
|
||||
}
|
||||
|
||||
impl CsvPreviewSettings {
|
||||
impl TabularDataPreviewSettings {
|
||||
/// `multiline_cells_enabled` only makes sense with `VariableList`, which
|
||||
/// supports per-row heights; `UniformList` requires every row to share one
|
||||
/// height, so multiline is never honored there regardless of the setting.
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
//! This module defines core operations and config of tabular data view (CSV table)
|
||||
//! This module defines core operations and config of the tabular data view
|
||||
//! It operates in 2 coordinate systems:
|
||||
//! - `DataCellId` - indices of src data cells
|
||||
//! - `DisplayCellId` - indices of data after applied transformations like sorting/filtering, which is used to render cell on the screen
|
||||
//!
|
||||
//! It's designed to contain core logic of operations without relying on `CsvPreviewView`, context or window handles.
|
||||
//! It's designed to contain core logic of operations without relying on `TabularDataPreviewPane`, context or window handles.
|
||||
|
||||
use std::{
|
||||
collections::{HashMap, HashSet},
|
||||
|
||||
@@ -257,12 +257,12 @@ mod tests {
|
||||
prop::sample::select(&["a", "b", "c"])
|
||||
}
|
||||
|
||||
/// Generates a small rectangular CSV table (header + data rows) built
|
||||
/// Generates a small rectangular table (header + data rows) built
|
||||
/// from a tiny value alphabet, so duplicate values across rows/columns
|
||||
/// are frequent enough to exercise cross-column blocking. Returns the
|
||||
/// column count alongside the CSV text since callers need it to bound
|
||||
/// column count alongside the table text since callers need it to bound
|
||||
/// generated column indices.
|
||||
fn csv_table() -> impl Strategy<Value = (usize, String)> {
|
||||
fn table_text_strategy() -> impl Strategy<Value = (usize, String)> {
|
||||
(2usize..=6, 2usize..=3).prop_flat_map(|(rows, cols)| {
|
||||
prop::collection::vec(prop::collection::vec(small_value(), cols), rows).prop_map(
|
||||
move |grid| {
|
||||
@@ -278,9 +278,9 @@ mod tests {
|
||||
})
|
||||
}
|
||||
|
||||
fn build_engine(csv_text: &str) -> TableDataEngine {
|
||||
fn build_engine(table_text: &str) -> TableDataEngine {
|
||||
let mut engine = TableDataEngine::default();
|
||||
engine.contents = Arc::new(TableLikeContent::from_str(csv_text.to_string()));
|
||||
engine.contents = Arc::new(TableLikeContent::from_str(table_text.to_string()));
|
||||
engine.calculate_available_filters();
|
||||
engine
|
||||
}
|
||||
@@ -353,17 +353,17 @@ mod tests {
|
||||
proptest! {
|
||||
#[test]
|
||||
fn filter_states_are_order_independent(
|
||||
(cols, csv_text) in csv_table(),
|
||||
(cols, table_text) in table_text_strategy(),
|
||||
raw_toggles in prop::collection::vec((0usize..3, 0usize..3), 0..8),
|
||||
) {
|
||||
let toggles = resolve_toggles(&build_engine(&csv_text), cols, &raw_toggles);
|
||||
let toggles = resolve_toggles(&build_engine(&table_text), cols, &raw_toggles);
|
||||
|
||||
let mut forward_engine = build_engine(&csv_text);
|
||||
let mut forward_engine = build_engine(&table_text);
|
||||
let forward = apply_and_snapshot(&mut forward_engine, cols, &toggles);
|
||||
|
||||
let mut reversed = toggles.clone();
|
||||
reversed.reverse();
|
||||
let mut backward_engine = build_engine(&csv_text);
|
||||
let mut backward_engine = build_engine(&table_text);
|
||||
let backward = apply_and_snapshot(&mut backward_engine, cols, &reversed);
|
||||
|
||||
prop_assert_eq!(forward, backward);
|
||||
|
||||
@@ -15,7 +15,7 @@ use ui::{
|
||||
};
|
||||
use workspace::{Item, Pane, Workspace};
|
||||
|
||||
use crate::{parser::EditorState, settings::CsvPreviewSettings, types::TableLikeContent};
|
||||
use crate::{parser::EditorState, settings::TabularDataPreviewSettings, types::TableLikeContent};
|
||||
|
||||
mod parser;
|
||||
mod renderer;
|
||||
@@ -33,7 +33,7 @@ impl FeatureFlag for TabularDataPreviewFeatureFlag {
|
||||
}
|
||||
register_feature_flag!(TabularDataPreviewFeatureFlag);
|
||||
|
||||
pub struct CsvPreviewView {
|
||||
pub struct TabularDataPreviewPane {
|
||||
pub(crate) engine: TableDataEngine,
|
||||
|
||||
pub(crate) focus_handle: FocusHandle,
|
||||
@@ -45,8 +45,8 @@ pub struct CsvPreviewView {
|
||||
/// Background task computing the display-to-data mapping after a filter/sort change.
|
||||
/// Stored here so that a new change cancels the previous in-flight computation.
|
||||
pub(crate) filter_sort_task: Option<Task<()>>,
|
||||
pub(crate) settings: CsvPreviewSettings,
|
||||
/// Performance metrics for debugging and monitoring CSV operations.
|
||||
pub(crate) settings: TabularDataPreviewSettings,
|
||||
/// Performance metrics for debugging and monitoring tabular data operations.
|
||||
pub(crate) performance_metrics: PerformanceMetrics,
|
||||
pub(crate) list_state: gpui::ListState,
|
||||
/// Cached row height, refreshed from the actual text line height on every render.
|
||||
@@ -59,12 +59,12 @@ pub struct CsvPreviewView {
|
||||
|
||||
pub fn init(cx: &mut App) {
|
||||
cx.observe_new(|workspace: &mut Workspace, _, _| {
|
||||
CsvPreviewView::register(workspace);
|
||||
TabularDataPreviewPane::register(workspace);
|
||||
})
|
||||
.detach()
|
||||
}
|
||||
|
||||
impl CsvPreviewView {
|
||||
impl TabularDataPreviewPane {
|
||||
pub(crate) fn sync_column_widths(&self, cx: &mut Context<Self>) {
|
||||
// plus 1 for the row identifier column
|
||||
let cols = self.engine.contents.headers.cols() + 1;
|
||||
@@ -93,14 +93,17 @@ impl CsvPreviewView {
|
||||
workspace.register_action_renderer(|div, _, _, cx| {
|
||||
div.when(cx.has_flag::<TabularDataPreviewFeatureFlag>(), |div| {
|
||||
div.on_action(cx.listener(|workspace, _: &OpenPreview, window, cx| {
|
||||
if let Some(editor) = Self::resolve_active_item_as_csv_editor(workspace, cx) {
|
||||
if let Some(editor) =
|
||||
Self::resolve_active_item_as_tabular_data_editor(workspace, cx)
|
||||
{
|
||||
let pane = workspace.active_pane().clone();
|
||||
Self::open_preview_in_pane(editor, pane, window, cx);
|
||||
}
|
||||
}))
|
||||
.on_action(cx.listener(
|
||||
|workspace, _: &OpenPreviewToTheSide, window, cx| {
|
||||
if let Some(editor) = Self::resolve_active_item_as_csv_editor(workspace, cx)
|
||||
if let Some(editor) =
|
||||
Self::resolve_active_item_as_tabular_data_editor(workspace, cx)
|
||||
{
|
||||
let pane = workspace.active_pane().clone();
|
||||
Self::open_preview_to_the_side_of_pane(
|
||||
@@ -146,9 +149,9 @@ impl CsvPreviewView {
|
||||
pane.activate_item(existing_view_idx, focus, focus, window, cx);
|
||||
});
|
||||
} else {
|
||||
let csv_preview = Self::new(&editor, window, cx);
|
||||
let preview_pane = Self::new(&editor, window, cx);
|
||||
pane.update(cx, |pane, cx| {
|
||||
pane.add_item(Box::new(csv_preview), focus, focus, None, window, cx);
|
||||
pane.add_item(Box::new(preview_pane), focus, focus, None, window, cx);
|
||||
});
|
||||
}
|
||||
cx.notify();
|
||||
@@ -159,7 +162,7 @@ impl CsvPreviewView {
|
||||
editor: &Entity<Editor>,
|
||||
cx: &App,
|
||||
) -> Option<usize> {
|
||||
pane.items_of_type::<CsvPreviewView>()
|
||||
pane.items_of_type::<TabularDataPreviewPane>()
|
||||
.find(|view| &view.read(cx).active_editor_state.editor == editor)
|
||||
.and_then(|view| pane.index_for_item(&view))
|
||||
}
|
||||
@@ -175,10 +178,10 @@ impl CsvPreviewView {
|
||||
cx.new(|cx| {
|
||||
let subscription = cx.subscribe(
|
||||
editor,
|
||||
|this: &mut CsvPreviewView, _editor, event: &EditorEvent, cx| {
|
||||
|this: &mut TabularDataPreviewPane, _editor, event: &EditorEvent, cx| {
|
||||
match event {
|
||||
EditorEvent::Edited { .. } | EditorEvent::DirtyChanged => {
|
||||
this.parse_csv_from_active_editor(true, cx);
|
||||
this.parse_from_active_editor(true, cx);
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
@@ -186,7 +189,7 @@ impl CsvPreviewView {
|
||||
);
|
||||
|
||||
let row_height = window.pixel_snap(window.line_height());
|
||||
let mut view = CsvPreviewView {
|
||||
let mut view = TabularDataPreviewPane {
|
||||
focus_handle: cx.focus_handle(),
|
||||
active_editor_state: EditorState {
|
||||
editor: editor.clone(),
|
||||
@@ -201,12 +204,12 @@ impl CsvPreviewView {
|
||||
list_state: gpui::ListState::new(contents.rows.len(), ListAlignment::Top, px(1.))
|
||||
.with_uniform_item_height(row_height),
|
||||
row_height,
|
||||
settings: CsvPreviewSettings::default(),
|
||||
settings: TabularDataPreviewSettings::default(),
|
||||
last_parse_end_time: None,
|
||||
engine: TableDataEngine::default(),
|
||||
};
|
||||
|
||||
view.parse_csv_from_active_editor(false, cx);
|
||||
view.parse_from_active_editor(false, cx);
|
||||
view
|
||||
})
|
||||
}
|
||||
@@ -263,17 +266,17 @@ impl CsvPreviewView {
|
||||
}));
|
||||
}
|
||||
|
||||
pub fn resolve_active_item_as_csv_editor(
|
||||
pub fn resolve_active_item_as_tabular_data_editor(
|
||||
workspace: &Workspace,
|
||||
cx: &mut Context<Workspace>,
|
||||
) -> Option<Entity<Editor>> {
|
||||
let editor = workspace
|
||||
.active_item(cx)
|
||||
.and_then(|item| item.act_as::<Editor>(cx))?;
|
||||
Self::is_csv_file(&editor, cx).then_some(editor)
|
||||
Self::is_tabular_data_file(&editor, cx).then_some(editor)
|
||||
}
|
||||
|
||||
pub fn is_csv_file(editor: &Entity<Editor>, cx: &App) -> bool {
|
||||
pub fn is_tabular_data_file(editor: &Entity<Editor>, cx: &App) -> bool {
|
||||
editor
|
||||
.read(cx)
|
||||
.buffer()
|
||||
@@ -286,15 +289,15 @@ impl CsvPreviewView {
|
||||
}
|
||||
}
|
||||
|
||||
impl Focusable for CsvPreviewView {
|
||||
impl Focusable for TabularDataPreviewPane {
|
||||
fn focus_handle(&self, _cx: &App) -> FocusHandle {
|
||||
self.focus_handle.clone()
|
||||
}
|
||||
}
|
||||
|
||||
impl EventEmitter<()> for CsvPreviewView {}
|
||||
impl EventEmitter<()> for TabularDataPreviewPane {}
|
||||
|
||||
impl Item for CsvPreviewView {
|
||||
impl Item for TabularDataPreviewPane {
|
||||
type Event = ();
|
||||
|
||||
fn tab_icon(&self, _window: &Window, _cx: &App) -> Option<Icon> {
|
||||
@@ -316,7 +319,7 @@ impl Item for CsvPreviewView {
|
||||
.file_name()
|
||||
.map(|name| format!("Preview {}", name.to_string_lossy()).into())
|
||||
})
|
||||
.unwrap_or_else(|| SharedString::from("CSV Preview"))
|
||||
.unwrap_or_else(|| SharedString::from("Tabular Data Preview"))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -360,13 +363,13 @@ impl PerformanceMetrics {
|
||||
}
|
||||
}
|
||||
|
||||
/// Holds state of column widths for a table component in CSV preview.
|
||||
/// Holds state of column widths for a table component in the tabular data preview.
|
||||
pub(crate) struct ColumnWidths {
|
||||
pub widths: Entity<ResizableColumnsState>,
|
||||
}
|
||||
|
||||
impl ColumnWidths {
|
||||
pub(crate) fn new(cx: &mut Context<CsvPreviewView>, cols: usize) -> Self {
|
||||
pub(crate) fn new(cx: &mut Context<TabularDataPreviewPane>, cols: usize) -> Self {
|
||||
Self {
|
||||
widths: cx.new(|_cx| {
|
||||
ResizableColumnsState::new(
|
||||
|
||||
@@ -7,7 +7,7 @@ mod table_cell;
|
||||
pub use table_like_content::*;
|
||||
mod table_like_content;
|
||||
|
||||
/// Line number information for CSV rows
|
||||
/// Line number information for table rows
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum LineNumber {
|
||||
/// Single line row
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
//! Type definitions for CSV table coordinates and cell identifiers.
|
||||
//! Type definitions for table coordinates and cell identifiers.
|
||||
//!
|
||||
//! Provides newtypes for self-documenting coordinate systems:
|
||||
//! - Display coordinates: Visual positions in rendered table
|
||||
//! - Data coordinates: Original CSV data positions
|
||||
//! - Data coordinates: Original data positions
|
||||
|
||||
use std::ops::Deref;
|
||||
|
||||
@@ -31,7 +31,7 @@ impl Deref for DisplayRow {
|
||||
}
|
||||
}
|
||||
|
||||
/// Original CSV row position.
|
||||
/// Original table row position.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
||||
pub struct DataRow(pub usize);
|
||||
|
||||
@@ -63,7 +63,7 @@ impl From<usize> for DataRow {
|
||||
}
|
||||
|
||||
///// Columns /////
|
||||
/// Data column position in CSV table. 0-based
|
||||
/// Data column position in the table. 0-based
|
||||
///
|
||||
/// Currently represents both display and data coordinate systems since
|
||||
/// column reordering is not yet implemented. When column reordering is added,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use text::Anchor;
|
||||
use ui::SharedString;
|
||||
|
||||
/// Position of a cell within the source CSV buffer
|
||||
/// Position of a cell within the source buffer
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct CellContentSpan {
|
||||
/// Start anchor of the cell content in the source buffer
|
||||
@@ -13,7 +13,7 @@ pub struct CellContentSpan {
|
||||
/// A table cell with its content and position in the source buffer
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum TableCell {
|
||||
/// Cell existing in the CSV
|
||||
/// Cell existing in the source data
|
||||
Real {
|
||||
/// Position of this cell in the source buffer
|
||||
position: CellContentSpan,
|
||||
|
||||
@@ -3,7 +3,7 @@ use feature_flags::FeatureFlagAppExt as _;
|
||||
use gpui::{AnyElement, Entity, Modifiers};
|
||||
use markdown_preview::markdown_preview_view::MarkdownPreviewView;
|
||||
use svg_preview::svg_preview_view::SvgPreviewView;
|
||||
use tabular_data_preview::{CsvPreviewView, TabularDataPreviewFeatureFlag};
|
||||
use tabular_data_preview::{TabularDataPreviewFeatureFlag, TabularDataPreviewPane};
|
||||
use ui::{Tooltip, prelude::*, text_for_keystroke};
|
||||
|
||||
use super::QuickActionBar;
|
||||
@@ -32,7 +32,7 @@ impl QuickActionBar {
|
||||
PreviewTarget::Svg(buffer)
|
||||
} else if let Some(editor) = editor
|
||||
&& cx.has_flag::<TabularDataPreviewFeatureFlag>()
|
||||
&& CsvPreviewView::is_csv_file(&editor, cx)
|
||||
&& TabularDataPreviewPane::is_tabular_data_file(&editor, cx)
|
||||
{
|
||||
PreviewTarget::TabularData(editor)
|
||||
} else {
|
||||
@@ -117,11 +117,13 @@ impl QuickActionBar {
|
||||
PreviewTarget::TabularData(editor) => {
|
||||
let editor = editor.clone();
|
||||
if open_to_the_side {
|
||||
CsvPreviewView::open_preview_to_the_side_of_pane(
|
||||
TabularDataPreviewPane::open_preview_to_the_side_of_pane(
|
||||
workspace, editor, pane, window, cx,
|
||||
);
|
||||
} else {
|
||||
CsvPreviewView::open_preview_in_pane(editor, pane, window, cx);
|
||||
TabularDataPreviewPane::open_preview_in_pane(
|
||||
editor, pane, window, cx,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user