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:
Oleksandr Kholiavko authored and GitHub committed 2026-08-18 12:28:30 +00:00
1 parent d0394b7c8c
commit 4aef01479b
16 files changed
+116 -110

No files matched your search

+20 -19
View File
@@ -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);
+3 -3
View File
@@ -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(
+1 -1
View File
@@ -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,
);
}
}
}