fix: quote CSV fields only when required
This commit is contained in:
+21
-6
@@ -677,6 +677,10 @@ fn append_record<'a>(
|
||||
if index > 0 {
|
||||
output.push(',');
|
||||
}
|
||||
if !value.contains([',', '"', '\r', '\n']) {
|
||||
output.push_str(value);
|
||||
continue;
|
||||
}
|
||||
output.push('"');
|
||||
for character in value.chars() {
|
||||
if character == '"' {
|
||||
@@ -755,6 +759,17 @@ fn moved_index(selected: Option<usize>, count: usize, delta: isize) -> Option<us
|
||||
mod tests {
|
||||
use super::moved_index;
|
||||
|
||||
#[test]
|
||||
fn csv_quotes_only_fields_with_delimiters_quotes_or_line_breaks() {
|
||||
let mut output = String::new();
|
||||
super::append_record(
|
||||
&mut output,
|
||||
["42", "00123", "界", "", "a,b", "a\"b", "a\rb", "a\nb"].into_iter(),
|
||||
false,
|
||||
);
|
||||
assert_eq!(output, "42,00123,界,,\"a,b\",\"a\"\"b\",\"a\rb\",\"a\nb\"\r\n");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rectangular_selection_copies_full_cells_and_resets_on_data_changes() -> crate::Result<()> {
|
||||
use super::{App, Focus};
|
||||
@@ -799,14 +814,14 @@ mod tests {
|
||||
);
|
||||
assert_eq!(
|
||||
app.selection_text(true, false).as_deref(),
|
||||
Some("\"b\",\"c\"\r\n\"a|b\",\"say \"\"hi\"\",界\"\r\n\"NULL\",\"<&>\\tail\"\r\n")
|
||||
Some("b,c\r\na|b,\"say \"\"hi\"\",界\"\r\nNULL,<&>\\tail\r\n")
|
||||
);
|
||||
assert_eq!(
|
||||
app.selection_text(false, false).as_deref(),
|
||||
Some("\"a|b\",\"say \"\"hi\"\",界\"\r\n\"NULL\",\"<&>\\tail\"\r\n")
|
||||
Some("a|b,\"say \"\"hi\"\",界\"\r\nNULL,<&>\\tail\r\n")
|
||||
);
|
||||
assert!(app.handle_rows_command(KeyEvent::new(KeyCode::Esc, KeyModifiers::NONE)));
|
||||
assert_eq!(app.selection_text(false, false).as_deref(), Some("\"a|b\"\r\n"));
|
||||
assert_eq!(app.selection_text(false, false).as_deref(), Some("a|b\r\n"));
|
||||
// A prefix cancels on focus changes rather than capturing a later key.
|
||||
app.handle_rows_command(key('y'));
|
||||
assert!(!app.handle_rows_command(KeyEvent::new(KeyCode::Tab, KeyModifiers::NONE)));
|
||||
@@ -814,7 +829,7 @@ mod tests {
|
||||
app.handle_rows_command(key('v'));
|
||||
app.handle_key(key('n'));
|
||||
assert!(app.selection_anchor.is_none());
|
||||
assert_eq!(app.selection_text(false, false).as_deref(), Some("\"101\"\r\n"));
|
||||
assert_eq!(app.selection_text(false, false).as_deref(), Some("101\r\n"));
|
||||
app.handle_rows_command(key('v'));
|
||||
app.handle_key(key('s'));
|
||||
assert!(app.selection_anchor.is_none());
|
||||
@@ -824,11 +839,11 @@ mod tests {
|
||||
app.query.value = "SELECT 42 AS answer".into();
|
||||
app.execute_query();
|
||||
assert!(app.selection_anchor.is_none());
|
||||
assert_eq!(app.selection_text(true, false).as_deref(), Some("\"answer\"\r\n\"42\"\r\n"));
|
||||
assert_eq!(app.selection_text(true, false).as_deref(), Some("answer\r\n42\r\n"));
|
||||
app.handle_rows_command(key('v'));
|
||||
app.query.value = "SELECT missing FROM nowhere".into();
|
||||
app.execute_query();
|
||||
assert_eq!(app.selection_text(false, false).as_deref(), Some("\"42\"\r\n"));
|
||||
assert_eq!(app.selection_text(false, false).as_deref(), Some("42\r\n"));
|
||||
assert!(app.selection_anchor.is_some());
|
||||
app.open_relation(Some(0));
|
||||
assert!(app.selection_anchor.is_none());
|
||||
|
||||
Reference in New Issue
Block a user