Subject: bug#72653: 29.4; csv-comment-start can no longer be nil

From: Joost Kremers <[email-masked]>
Date: Fri, 16 Aug 2024 08:48:32 +0200

The doc string of the variable 'csv-comment-start' states that it is allowed to
be nil:

   String that starts a comment line, or nil if no comment syntax.

However, since commit 388bcb9a77118d7b7d9c42aa8b3f9fa2c892b930 (Fix
'csv-guess-separator' being confused by comments) this is no longer the case,
because the variable is passed to 'string-to-char', which does not accept nil as
input.

As a result, if 'csv-comment-start' is nil, the separator cannot be guessed
anymore, which may result in the wrong separator being guessed.

Recipe to reproduce:

- Start emacs -Q -L /path/to/csv-mode-1.27 (the current version on ELPA).
- Load 'csv-mode.el'.
- Set 'csv-comment-start-default' to nil.
- Open a CSV file with non-standard separator (e.g., TAB, though make sure the
  file extension is '.csv', not '.tsv'.)
- Check the buffer-local value of 'csv-separators': it should be ("\t"), but it
  is ("," "\t").

If you try to add a column to a line (hit TAB with point at EOL), you'll notice
a comma being added as separator.

Tiny patch attached.

>From f7ab676679b2ca4c3772f71b206cc4932025a0cc Mon Sep 17 00:00:00 2001
From: Joost Kremers <[email-masked]>
Date: Fri, 16 Aug 2024 08:45:05 +0200
Subject: [PATCH] Guard for csv-comment-start being nil

* csv-mode.el (csv--separator-candidates): Make sure
'csv-comment-start' is non-nil before passing to 'string-to-char'.
---
 csv-mode.el | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/csv-mode.el b/csv-mode.el
index 3dc6ddd..d90878f 100644
--- a/csv-mode.el
+++ b/csv-mode.el
@@ -1909,7 +1909,8 @@ When CUTOFF is passed, look only at the first CUTOFF number of characters."
       (when (and (not (gethash c chars))
                  (or (memq c '(?\t ?\C-_))
                      (not (or (memq c '(?. ?/ ?\" ?'))
-                              (= c (string-to-char csv-comment-start))
+                              (and csv-comment-start
+                                   (= c (string-to-char csv-comment-start)))
                               (memq (get-char-code-property c 'general-category)
                                     '(Lu Ll Lt Lm Lo Nd Nl No Ps Pe Cc Co))))))
         (puthash c t chars)))
-- 
2.46.0

In GNU Emacs 29.4 (build 1, x86_64-pc-linux-gnu, GTK+ Version 3.24.42, cairo
version 1.18.0)
System Description: Arch Linux

Configured using:
 'configure --with-pgtk --with-native-compilation=aot --sysconfdir=/etc
 --prefix=/usr --libexecdir=/usr/lib --with-tree-sitter --localstatedir=/var
 --with-cairo --disable-build-details --with-harfbuzz --with-libsystemd
 --with-modules 'CFLAGS=-march=x86-64 -mtune=generic -O2 -pipe -fno-plt
 -fexceptions -Wp,-D_FORTIFY_SOURCE=3 -Wformat -Werror=format-security
 -fstack-clash-protection -fcf-protection -fno-omit-frame-pointer
 -mno-omit-leaf-frame-pointer -g
 -ffile-prefix-map=/build/emacs/src=/usr/src/debug/emacs -flto=auto'
 'LDFLAGS=-Wl,-O1 -Wl,--sort-common -Wl,--as-needed -Wl,-z,relro -Wl,-z,now
 -Wl,-z,pack-relative-relocs -flto=auto' 'CXXFLAGS=-march=x86-64 -mtune=generic
 -O2 -pipe -fno-plt -fexceptions -Wp,-D_FORTIFY_SOURCE=3 -Wformat
 -Werror=format-security -fstack-clash-protection -fcf-protection
 -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer -Wp,-D_GLIBCXX_ASSERTIONS
 -g -ffile-prefix-map=/build/emacs/src=/usr/src/debug/emacs -flto=auto''
Configured features:
ACL CAIRO DBUS FREETYPE GIF GLIB GMP GNUTLS GPM GSETTINGS HARFBUZZ JPEG JSON
LCMS2 LIBOTF LIBSYSTEMD LIBXML2 MODULES NATIVE_COMP NOTIFY INOTIFY PDUMPER PGTK
PNG RSVG SECCOMP SOUND SQLITE3 THREADS TIFF TOOLKIT_SCROLL_BARS TREE_SITTER WEBP
XIM GTK3 ZLIB
Important settings:
  value of $LANG: en_GB.UTF-8
  locale-coding-system: utf-8-unix

Major mode: VTerm

Minor modes in effect:
  mu4e-modeline-mode: t
  flycheck-indicator-mode: t
  global-flycheck-eglot-mode: t
  minions-mode: t
  doom-modeline-mode: t
  which-key-mode: t
  global-atomic-chrome-edit-mode: t
  marginalia-mode: t
  all-the-icons-completion-mode: t
  company-prescient-mode: t
  prescient-persist-mode: t
  vertico-multiform-mode: t
  eros-mode: t
  eglot-booster-mode: t
  vertico-mode: t
  global-diff-hl-mode: t
  global-git-commit-mode: t
  global-treesit-auto-mode: t
  global-org-modern-mode: t
  denote-menu-bar-mode: t
  shell-dirtrack-mode: t
  company-quickhelp-mode: t
  company-quickhelp-local-mode: t
  global-company-mode: t
  company-mode: t
  csv-field-index-mode: t
  override-global-mode: t
  server-mode: t
  repeat-mode: t
  winner-mode: t
  electric-pair-mode: t
  recentf-mode: t
  delete-selection-mode: t
  tooltip-mode: t
  global-eldoc-mode: t
  show-paren-mode: t
  mouse-wheel-mode: t
  tool-bar-mode: t
  menu-bar-mode: t
  file-name-shadow-mode: t
  global-font-lock-mode: t
  font-lock-mode: t
  buffer-read-only: t
  column-number-mode: t
  line-number-mode: t
  transient-mark-mode: t
  auto-composition-mode: t
  auto-encryption-mode: t
  auto-compression-mode: t
  auto-save-visited-mode: t

Load-path shadows:
~/src/parsebib/parsebib hides /home/joost/.emacs.d/elpa/parsebib-20230228.1530/parsebib
~/.emacs.d/lisp/custom hides /usr/share/emacs/29.4/lisp/custom
/home/joost/.emacs.d/elpa/transient-20240814.1922/transient hides /usr/share/emacs/29.4/lisp/transient

Features:
(shadow guess-language emacsbug cl-print help-fns radix-tree descr-text avy
gnus-cite smiley shr-color mm-archive mail-extr qp textsec uni-scripts
idna-mapping ucs-normalize uni-confusable textsec-check visual-fill-column
display-line-numbers mu4e-settings gnus-dired mu4e mu4e-org mu4e-notification
mu4e-main smtpmail mu4e-view mu4e-mime-parts mu4e-headers mu4e-thread
mu4e-actions mu4e-compose mu4e-draft gnus-msg mu4e-search mu4e-lists
mu4e-bookmarks mu4e-mark mu4e-message flow-fill mule-util mu4e-contacts
mu4e-update mu4e-folders mu4e-context mu4e-query-items mu4e-server mu4e-modeline
mu4e-vars mu4e-helpers mu4e-config mu4e-window mu4e-obsolete
display-fill-column-indicator flyspell ispell flycheck-indicator flycheck-ledger
flycheck-eglot flycheck-posframe flycheck eldoc-box jk-input-methods quail
solarized-light-theme solarized-theme solarized solarized-faces wgrep-ag wgrep
csv2ledger vterm bookmark term disp-table ehelp vterm-module term/xterm xterm
ielm minions doom-modeline doom-modeline-segments doom-modeline-env
doom-modeline-core shrink-path f nerd-icons nerd-icons-faces nerd-icons-data
nerd-icons-data-mdicon nerd-icons-data-flicon nerd-icons-data-codicon
nerd-icons-data-devicon nerd-icons-data-sucicon nerd-icons-data-wicon
nerd-icons-data-faicon nerd-icons-data-powerline nerd-icons-data-octicon
nerd-icons-data-pomicon nerd-icons-data-ipsicon which-key atomic-chrome iimage
image+ image-file image-converter marginalia all-the-icons-completion
company-prescient prescient char-fold orderless vertico-multiform
dockerfile-mode sh-script smie executable impatient-mode htmlize jupyter
python-pytest edebug eros macrostep checkdoc paredit eglot-booster eglot
external-completion array jsonrpc ert debug backtrace flymake-proc flymake imenu
org-linenote vertico projectile lisp-mnt grep ibuf-ext ibuffer ibuffer-loaddefs
ag vc-svn compile find-dired s diff-hl log-view vc-dir ewoc vc vc-dispatcher
diff-mode git-commit magit-git magit-base magit-section cursor-sensor crm
with-editor transient log-edit pcvs-util add-log autorevert aggressive-indent
nswbuff finder-inf yaml-mode yaml treesit-auto reftex reftex-loaddefs
reftex-vars tab-jump-out yasnippet-snippets yasnippet company-org-block
org-modern org-settings org-clock ob-jupyter jupyter-tramp tramp-cache
time-stamp jupyter-server jupyter-server-kernel jupyter-rest-api url-http
url-auth url-gw nsm jupyter-org-extensions jupyter-org-client jupyter-repl
jupyter-widget-client websocket bindat simple-httpd jupyter-client
jupyter-kernel jupyter-monads jupyter-messages hmac-def jupyter-mime
jupyter-kernelspec jupyter-env jupyter-base eieio-base ob-shell ob-scheme
ob-clojure ob-python python compat compat-30 treesit ol-w3m org-tempo tempo
ol-rmail ol-mhe ol-irc ol-info ol-gnus nnselect gnus-art mm-uu mml2015 mm-view
mml-smime smime gnutls dig gnus-sum gnus-group gnus-undo gnus-start gnus-dbus
gnus-cloud nnimap nnmail mail-source utf7 nnoo gnus-spec gnus-int gnus-range
message sendmail yank-media rfc822 mml mml-sec epa derived epg rfc6068
epg-config mm-decode mm-bodies mm-encode mail-parse rfc2231 rfc2047 rfc2045
ietf-drums mailabbrev gmm-utils mailheader gnus-win ol-eww eww thingatpt shr
pixel-fill kinsoku svg puny mm-url gnus nnheader gnus-util text-property-search
mail-utils range mm-util mail-prsvr ol-doi org-link-doi ol-docview doc-view
filenotify jka-compr image-mode exif ol-bibtex ol-bbdb org-element org-persist
xdg org-id org-refile avl-tree dom org ob ob-tangle ob-ref ob-lob ob-table
ob-exp org-macro org-src ob-comint org-pcomplete org-list org-footnote org-faces
org-entities noutline outline ob-emacs-lisp ob-core ob-eval org-cycle org-table
ol org-fold org-fold-core org-keys oc org-loaddefs find-func cal-menu calendar
cal-loaddefs org-version org-compat org-macs denote dired dired-loaddefs tramp
tramp-loaddefs trampver tramp-integration tramp-compat shell pcomplete comint
ansi-osc parse-time format-spec ansi-color mixed-pitch face-remap biblio
biblio-download biblio-dissemin biblio-ieee biblio-hal biblio-dblp
biblio-crossref biblio-arxiv timezone biblio-doi biblio-core let-alist url-queue
url-file ido hl-line bibtex iso8601 time-date adaptive-wrap goggles comp
comp-cstr warnings rx pulse color posframe hydra lv use-package-bind-key
company-quickhelp pos-tip all-the-icons all-the-icons-faces data-material
data-weathericons data-octicons data-fileicons data-faicons data-alltheicons
company-keywords company-etags etags fileloop xref project company-gtags
company-dabbrev-code company-dabbrev company-ipa company-files company-clang
company-cmake company-semantic company-template company-css company-capf company
use-package-ensure whitespace literate-scratch jk-functions advice csv-mode sort
dash eshell esh-cmd generator esh-ext esh-opt esh-proc esh-io esh-arg esh-module
esh-groups esh-util files-x notifications dbus xml use-package-core cl-extra
help-mode edmacro kmacro bind-key server repeat winner ring elec-pair recentf
tree-widget delsel help-at-pt cus-edit pp cus-load icons wid-edit
all-the-icons-completion-autoloads all-the-icons-autoloads apheleia-autoloads
easy-mmode async-autoloads avy-autoloads boxquote-autoloads
casual-calc-autoloads casual-info-autoloads casual-lib-autoloads citar-autoloads
citeproc-autoloads clojure-mode-autoloads company-auctex-autoloads
auctex-autoloads tex-site company-box-autoloads company-prescient-autoloads
company-quickhelp-autoloads consult-denote-autoloads consult-flycheck-autoloads
csv-mode-autoloads denote-autoloads devdocs-browser-autoloads diff-hl-autoloads
docker-autoloads dockerfile-mode-autoloads doom-modeline-autoloads
eglot-booster-autoloads eldoc-box-autoloads embark-consult-autoloads
consult-autoloads embark-autoloads eros-autoloads expand-region-autoloads
flycheck-clj-kondo-autoloads flycheck-eglot-autoloads goggles-autoloads
gptel-autoloads guess-language-autoloads hydra-autoloads ialign-autoloads
impatient-mode-autoloads htmlize-autoloads company-autoloads js2-mode-autoloads
json-process-client-autoloads jsonian-autoloads jupyter-autoloads
kivy-mode-autoloads ledger-mode-autoloads literate-scratch-autoloads
lv-autoloads macrostep-autoloads magit-autoloads git-commit-autoloads
magit-section-autoloads marginalia-autoloads markdown-mode-autoloads
minions-autoloads multiple-cursors-autoloads nerd-icons-autoloads
numpydoc-autoloads nushell-ts-mode-autoloads orderless-autoloads
org-linenote-autoloads org-modern-autoloads paredit-autoloads parsebib-autoloads
pdf-tools-autoloads popup-autoloads pos-tip-autoloads posframe-autoloads
prescient-autoloads projectile-autoloads python-pytest-autoloads
realgud-autoloads realgud-recursive-autoloads loc-changes-autoloads
load-relative-autoloads f-autoloads simple-httpd-autoloads sly-overlay-autoloads
sly-autoloads solarized-theme-autoloads string-inflection-autoloads
tab-jump-out-autoloads tablist-autoloads test-simple-autoloads tide-autoloads
flycheck-autoloads dash-autoloads track-changes-autoloads transient-autoloads
treesit-auto-autoloads vertico-autoloads vterm-autoloads vundo-autoloads
web-mode-autoloads websocket-autoloads which-key-autoloads with-editor-autoloads
info compat-autoloads yaml-autoloads yaml-mode-autoloads
yasnippet-snippets-autoloads yasnippet-autoloads zmq-autoloads package
browse-url url url-proxy url-privacy url-expand url-methods url-history
url-cookie generate-lisp-file url-domsuf url-util mailcap url-handlers url-parse
auth-source cl-seq eieio eieio-core cl-macs password-cache json subr-x map
byte-opt gv bytecomp byte-compile url-vars cl-loaddefs cl-lib pcase rmc
iso-transl tooltip cconv eldoc paren electric uniquify ediff-hook vc-hooks
lisp-float-type elisp-mode mwheel term/pgtk-win pgtk-win term/common-win
pgtk-dnd tool-bar dnd fontset image regexp-opt fringe tabulated-list replace
newcomment text-mode lisp-mode prog-mode register page tab-bar menu-bar
rfn-eshadow isearch easymenu timer select scroll-bar mouse jit-lock font-lock
syntax font-core term/tty-colors frame minibuffer nadvice seq simple cl-generic
indonesian philippine cham georgian utf-8-lang misc-lang vietnamese tibetan thai
tai-viet lao korean japanese eucjp-ms cp51932 hebrew greek romanian slovak czech
european ethiopic indian cyrillic chinese composite emoji-zwj charscript
charprop case-table epa-hook jka-cmpr-hook help abbrev obarray oclosure
cl-preloaded button loaddefs theme-loaddefs faces cus-face macroexp files window
text-properties overlay sha1 md5 base64 format env code-pages mule custom widget
keymap hashtable-print-readable backquote threads dbusbind inotify
dynamic-setting system-font-setting font-render-setting cairo gtk pgtk lcms2
multi-tty make-network-process native-compile emacs)

Memory information:
((conses 16 1158663 176414)
 (symbols 48 71132 38)
 (strings 32 375912 8612)
 (string-bytes 1 10201651)
 (vectors 16 132548)
 (vector-slots 8 2847191 164786)
 (floats 8 1406 844)
 (intervals 56 5983 2223)
 (buffers 984 22))

-- 
Joost Kremers
Life has its moments