all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
From: Joost Kremers <joostkremers@fastmail.fm>
To: Philip Kaludercic <philipk@posteo.net>
Cc: Emacs Devel <emacs-devel@gnu.org>
Subject: Re: [PATCH] csv-mode.el: Add function for reading a CSV line
Date: Wed, 22 May 2024 18:21:19 +0200	[thread overview]
Message-ID: <86pltdizr4.fsf@fastmail.fm> (raw)
In-Reply-To: <87r0dthli0.fsf@posteo.net> (Philip Kaludercic's message of "Wed,  22 May 2024 16:14:31 +0000")

[-- Attachment #1: Type: text/plain, Size: 719 bytes --]

On Wed, May 22 2024, Philip Kaludercic wrote:
[patch]
> Seems fine to me.  I'd apply it if there are no objections.  Until then,
> you can prepare to modify your package to use this change.

I was just about to suggest one more test. Specifically:

```
(should (equal (let ((csv-field-quotes '("\"" "'")))
                   (csv--unquote-value "'Hello, \"World\"'"))
                 "Hello, \"World\""))
```

It tests the case where the user defined more than one possible quote character,
one being used to quote the field and the other being used inside the field.

The attached patch adds this test but is otherwise identical to the previous
one.

Otherwise, thanks! :-)


-- 
Joost Kremers
Life has its moments



[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-Add-function-for-reading-a-CSV-line-and-return-its-v.patch --]
[-- Type: text/x-patch, Size: 3852 bytes --]

From 2a37f695ffe5757b0f22ffe63d312d1407122e3a Mon Sep 17 00:00:00 2001
From: Joost Kremers <joostkremers@fastmail.com>
Date: Wed, 22 May 2024 00:07:34 +0200
Subject: [PATCH] Add function for reading a CSV line and return its values as
 a list.

* (csv-parse-current-row): New function; unlike csv--collect-fields,
  unquotes the field values.
* (csv--unquote-value): New function.
---
 csv-mode-tests.el | 26 ++++++++++++++++++++++++++
 csv-mode.el       | 26 +++++++++++++++++++++++++-
 2 files changed, 51 insertions(+), 1 deletion(-)

diff --git a/csv-mode-tests.el b/csv-mode-tests.el
index 0caeab7..12e009e 100644
--- a/csv-mode-tests.el
+++ b/csv-mode-tests.el
@@ -144,5 +144,31 @@
              (csv--separator-score ?\; csv-tests--data
                                    (length csv-tests--data)))))
 
+(ert-deftest csv-tests-unquote-value ()
+  (should (equal (csv--unquote-value "Hello, World")
+                 "Hello, World"))
+  (should (equal (csv--unquote-value "\"Hello, World\"")
+                 "Hello, World"))
+  (should (equal (csv--unquote-value "Hello, \"\"World")
+                 "Hello, \"\"World"))
+  (should (equal (csv--unquote-value "\"Hello, \"\"World\"\"\"")
+                 "Hello, \"World\""))
+  (should (equal (csv--unquote-value "'Hello, World'")
+                 "'Hello, World'"))
+  (should (equal (let ((csv-field-quotes '("\"" "'")))
+                   (csv--unquote-value "\"Hello, World'"))
+                 "\"Hello, World'"))
+  (should (equal (let ((csv-field-quotes '("\"" "'")))
+                   (csv--unquote-value "'Hello, World'"))
+                 "Hello, World"))
+  (should (equal (let ((csv-field-quotes '("\"" "'")))
+                   (csv--unquote-value "'Hello, ''World'''"))
+                 "Hello, 'World'"))
+  (should (equal (let ((csv-field-quotes '("\"" "'")))
+                   (csv--unquote-value "'Hello, \"World\"'"))
+                 "Hello, \"World\""))
+  (should (equal (csv--unquote-value "|Hello, World|")
+                 "|Hello, World|")))
+
 (provide 'csv-mode-tests)
 ;;; csv-mode-tests.el ends here
diff --git a/csv-mode.el b/csv-mode.el
index f639dcf..ebcd9da 100644
--- a/csv-mode.el
+++ b/csv-mode.el
@@ -4,7 +4,7 @@
 
 ;; Author: "Francis J. Wright" <F.J.Wright@qmul.ac.uk>
 ;; Maintainer: emacs-devel@gnu.org
-;; Version: 1.23
+;; Version: 1.24
 ;; Package-Requires: ((emacs "27.1") (cl-lib "0.5"))
 ;; Keywords: convenience
 
@@ -107,6 +107,10 @@
 
 ;;; News:
 
+;; Since 1.24
+;; - New function `csv--unquote-value'.
+;; - New function `csv-parse-current-row'.
+
 ;; Since 1.21:
 ;; - New command `csv-insert-column'.
 ;; - New config var `csv-align-min-width' for `csv-align-mode'.
@@ -1400,6 +1404,26 @@ point is assumed to be at the beginning of the line."
 	      (forward-char)))
 	(nreverse fields)))))
 
+(defun csv--unquote-value (value)
+  "Remove quotes around VALUE.
+If VALUE contains escaped quote characters, un-escape them.  If
+VALUE is not quoted, return it unchanged."
+  (save-match-data
+    (let ((quote-regexp (apply #'concat `("[" ,@csv-field-quotes "]"))))
+      (if-let (((string-match (concat "^\\(" quote-regexp "\\)\\(.*\\)\\(" quote-regexp "\\)$") value))
+               (quote-char (match-string 1 value))
+               ((equal quote-char (match-string 3 value)))
+               (unquoted (match-string 2 value)))
+          (replace-regexp-in-string (concat quote-char quote-char) quote-char unquoted)
+        value))))
+
+(defun csv-parse-current-row ()
+  "Parse the current CSV line.
+Return the field values as a list."
+  (save-mark-and-excursion
+    (goto-char (line-beginning-position))
+    (mapcar #'csv--unquote-value (csv--collect-fields (line-end-position)))))
+
 (defvar-local csv--header-line nil)
 (defvar-local csv--header-hscroll nil)
 (defvar-local csv--header-string nil)
-- 
2.45.1


  reply	other threads:[~2024-05-22 16:21 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-05-21 22:55 [PATCH] csv-mode.el: Add function for reading a CSV line Joost Kremers
2024-05-22  6:17 ` Philip Kaludercic
2024-05-22  7:00   ` Joost Kremers
2024-05-22 16:14     ` Philip Kaludercic
2024-05-22 16:21       ` Joost Kremers [this message]
2024-05-25  8:26         ` Philip Kaludercic
2024-05-26  4:07   ` Stefan Monnier via Emacs development discussions.
2024-05-26  8:08     ` Joost Kremers

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=86pltdizr4.fsf@fastmail.fm \
    --to=joostkremers@fastmail.fm \
    --cc=emacs-devel@gnu.org \
    --cc=philipk@posteo.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this external index

	https://git.savannah.gnu.org/cgit/emacs.git
	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.