diff --git a/src/vs/workbench/browser/positronDataGrid/components/dataGridColumnHeader.css b/src/vs/workbench/browser/positronDataGrid/components/dataGridColumnHeader.css
index d3169511241..4709afa9e85 100644
--- a/src/vs/workbench/browser/positronDataGrid/components/dataGridColumnHeader.css
+++ b/src/vs/workbench/browser/positronDataGrid/components/dataGridColumnHeader.css
@@ -84,6 +84,14 @@
font-weight: var(--positron-data-grid-column-header-title-font-weight);
}
+.data-grid-column-header
+.content
+.title-description
+.title
+.whitespace {
+ opacity: 50%;
+}
+
.data-grid-column-header
.content
.title-description
diff --git a/src/vs/workbench/browser/positronDataGrid/components/dataGridColumnHeader.tsx b/src/vs/workbench/browser/positronDataGrid/components/dataGridColumnHeader.tsx
index d74e6aad8e3..ea013a7aeb0 100644
--- a/src/vs/workbench/browser/positronDataGrid/components/dataGridColumnHeader.tsx
+++ b/src/vs/workbench/browser/positronDataGrid/components/dataGridColumnHeader.tsx
@@ -17,7 +17,7 @@ import { selectionType } from '../utilities/mouseUtilities.js';
import { VerticalSplitter } from '../../../../base/browser/ui/positronComponents/splitters/verticalSplitter.js';
import { ColumnSelectionState } from '../classes/dataGridInstance.js';
import { usePositronDataGridContext } from '../positronDataGridContext.js';
-import { getDisplayedColumnName } from '../../../services/positronDataExplorer/common/utils.js';
+import { renderLeadingTrailingWhitespace } from '../../../services/positronDataExplorer/browser/components/tableDataCell.js';
/**
* Constants.
@@ -104,7 +104,7 @@ export const DataGridColumnHeader = (props: DataGridColumnHeaderProps) => {
// Determine whether the column is selected.
const selected = (columnSelectionState & ColumnSelectionState.Selected) !== 0;
- const displayedColumnName = getDisplayedColumnName(props.column?.name);
+ const renderedColumn = renderLeadingTrailingWhitespace(props.column?.name);
// Render.
return (
@@ -140,7 +140,7 @@ export const DataGridColumnHeader = (props: DataGridColumnHeaderProps) => {
}}
>
-
{displayedColumnName}
+
{renderedColumn}
{props.column?.description &&
{props.column.description}
}
diff --git a/src/vs/workbench/services/positronDataExplorer/browser/components/columnSummaryCell.css b/src/vs/workbench/services/positronDataExplorer/browser/components/columnSummaryCell.css
index 58a5fcddb2f..c48d06d350a 100644
--- a/src/vs/workbench/services/positronDataExplorer/browser/components/columnSummaryCell.css
+++ b/src/vs/workbench/services/positronDataExplorer/browser/components/columnSummaryCell.css
@@ -91,6 +91,10 @@
grid-column: title / sparkline;
}
+.data-grid-row-cell .content .column-summary .basic-info .column-name .whitespace {
+ opacity: 50%;
+}
+
/* column-sparkline */
.data-grid-row-cell .content .column-summary .basic-info .column-sparkline {
diff --git a/src/vs/workbench/services/positronDataExplorer/browser/components/columnSummaryCell.tsx b/src/vs/workbench/services/positronDataExplorer/browser/components/columnSummaryCell.tsx
index 0a4103f8b10..c7f4783cc96 100644
--- a/src/vs/workbench/services/positronDataExplorer/browser/components/columnSummaryCell.tsx
+++ b/src/vs/workbench/services/positronDataExplorer/browser/components/columnSummaryCell.tsx
@@ -24,7 +24,7 @@ import { ColumnProfileDatetime } from './columnProfileDatetime.js';
import { TableSummaryDataGridInstance } from '../tableSummaryDataGridInstance.js';
import { ColumnDisplayType, ColumnProfileType, ColumnSchema } from '../../../languageRuntime/common/positronDataExplorerComm.js';
import { dataExplorerExperimentalFeatureEnabled } from '../../common/positronDataExplorerExperimentalConfig.js';
-import { getDisplayedColumnName } from '../../common/utils.js';
+import { renderLeadingTrailingWhitespace } from './tableDataCell.js';
/**
* Constants.
@@ -355,6 +355,8 @@ export const ColumnSummaryCell = (props: ColumnSummaryCellProps) => {
break;
}
+ const renderedColumn = renderLeadingTrailingWhitespace(props.columnSchema.column_name);
+
// Determine whether this is the cursor.
const cursor = props.columnIndex === props.instance.cursorRowIndex;
@@ -414,7 +416,7 @@ export const ColumnSummaryCell = (props: ColumnSummaryCellProps) => {
onMouseLeave={() => props.hoverService.hideHover()}
/>
- {getDisplayedColumnName(props.columnSchema.column_name)}
+ {renderedColumn}
{!expanded &&
}
diff --git a/src/vs/workbench/services/positronDataExplorer/browser/components/tableDataCell.tsx b/src/vs/workbench/services/positronDataExplorer/browser/components/tableDataCell.tsx
index 809ae0e94f1..76c046cde43 100644
--- a/src/vs/workbench/services/positronDataExplorer/browser/components/tableDataCell.tsx
+++ b/src/vs/workbench/services/positronDataExplorer/browser/components/tableDataCell.tsx
@@ -23,33 +23,28 @@ interface TableDataCellProps {
dataCell: DataCell;
}
-/**
- * TableDataCell component.
- * @param props A TableDataCellProps that contains the component properties.
- * @returns The rendered component.
- */
-export const TableDataCell = (props: TableDataCellProps) => {
- const EMPTY_SPACE_SYMBOL = '\u00B7';
+export function renderLeadingTrailingWhitespace(text: string | undefined) {
+ const parts: (string | JSX.Element)[] = [];
- let isSpecialValue = props.dataCell.kind !== DataCellKind.NON_NULL;
+ text = text ?? '';
- // Render empty strings as special value
- // Initialize rendered output parts
- const parts: (string | JSX.Element)[] = [];
- const formattedText = props.dataCell.formatted
- .replace(/\r/g, '\\r')
- .replace(/\n/g, '\\n');
+ if (text === '') {
+ // TODO: is this what we want?
+ return [
{''}];
+ }
+
+ const EMPTY_SPACE_SYMBOL = '\u00B7';
// Handle text that is only whitespace
- if (formattedText.trim() === '') {
+ if (text.trim() === '') {
parts.push(
- {EMPTY_SPACE_SYMBOL.repeat(formattedText.length)}
+ {EMPTY_SPACE_SYMBOL.repeat(text.length)}
);
} else {
// Handle leading whitespace
- const leadingMatch = formattedText.match(/^\s+/);
+ const leadingMatch = text.match(/^\s+/);
if (leadingMatch) {
parts.push(
@@ -59,11 +54,11 @@ export const TableDataCell = (props: TableDataCellProps) => {
}
// Add the main content
- const mainContent = formattedText.trim();
+ const mainContent = text.trim();
parts.push(mainContent);
// Handle trailing whitespace
- const trailingMatch = formattedText.match(/\s+$/);
+ const trailingMatch = text.match(/\s+$/);
if (trailingMatch) {
parts.push(
@@ -72,6 +67,26 @@ export const TableDataCell = (props: TableDataCellProps) => {
);
}
}
+
+ return parts;
+}
+
+/**
+ * TableDataCell component.
+ * @param props A TableDataCellProps that contains the component properties.
+ * @returns The rendered component.
+ */
+export const TableDataCell = (props: TableDataCellProps) => {
+ // Render empty strings as special value
+ // Initialize rendered output parts
+ const formattedText = props.dataCell.formatted
+ .replace(/\r/g, '\\r')
+ .replace(/\n/g, '\\n');
+
+ const parts = renderLeadingTrailingWhitespace(formattedText);
+
+ let isSpecialValue = props.dataCell.kind !== DataCellKind.NON_NULL;
+
let renderedOutput = parts;
if (props.dataCell.kind === DataCellKind.NON_NULL && formattedText === '') {
isSpecialValue = true;
diff --git a/src/vs/workbench/services/positronDataExplorer/common/utils.ts b/src/vs/workbench/services/positronDataExplorer/common/utils.ts
index 1f35b5d9844..db92c73ea0a 100644
--- a/src/vs/workbench/services/positronDataExplorer/common/utils.ts
+++ b/src/vs/workbench/services/positronDataExplorer/common/utils.ts
@@ -30,20 +30,3 @@ export const arrayFromIndexRange = (startIndex: number, endIndex: number) =>
export const linearConversion = (value: number, from: Range, to: Range) =>
((value - from.min) / (from.max - from.min)) * (to.max - to.min) + to.min;
-
-/**
- * Add quoting to column name in case it is an empty string or contains leading whitespace.
- * @param name The column name from the backend
- * @returns A modified column name that helps distinguish whitespace
- */
-export function getDisplayedColumnName(name: string | undefined) {
- let result = name ?? '';
-
- const EMPTY_SPACE_SYMBOL = '\u2423';
- // If a column name is an empty string (allowed by pandas, at least) or contains
- // leading whitespace, then we surround the column name with quotations.
- if (result === '' || result.match(/^\s/)) {
- result = `"${result}"`.replace(/ /g, EMPTY_SPACE_SYMBOL);
- }
- return result;
-}