GNU bug report logs - #71325
30.0.50; multiline entries in tabulated-lists are left-aligned

Previous Next

Package: emacs;

Reported by: Andrey Listopadov <andreyorst <at> gmail.com>

Date: Sun, 2 Jun 2024 13:16:02 UTC

Severity: normal

Found in version 30.0.50

To reply to this bug, email your comments to 71325 AT debbugs.gnu.org.

Toggle the display of automated, internal messages from the tracker.

View this report as an mbox folder, status mbox, maintainer mbox


Report forwarded to bug-gnu-emacs <at> gnu.org:
bug#71325; Package emacs. (Sun, 02 Jun 2024 13:16:02 GMT) Full text and rfc822 format available.

Acknowledgement sent to Andrey Listopadov <andreyorst <at> gmail.com>:
New bug report received and forwarded. Copy sent to bug-gnu-emacs <at> gnu.org. (Sun, 02 Jun 2024 13:16:02 GMT) Full text and rfc822 format available.

Message #5 received at submit <at> debbugs.gnu.org (full text, mbox):

From: Andrey Listopadov <andreyorst <at> gmail.com>
To: bug-gnu-emacs <at> gnu.org
Subject: 30.0.50; multiline entries in tabulated-lists are left-aligned
Date: Sun, 02 Jun 2024 16:12:31 +0300
Hello! I was working with tabulated lists, and noticed, that multiline
entries are not properly inserted, when the column is not the first
one. E.g. this multiline entry:

tabulated-list-format:
[("1" 3 t) ("2" 10 t) ("3" 4 t)]

tabulated-list-entries:
((nil ["foo" "bar
baz
qux" "quux"]))

Is shown like this:

1   2          3
foo bar
baz
qux            quux

moreover, I can't set the second column's width to 3, as with the rest
ones, because it will truncate the string not accounting to multiline
widths:

1   2    3
foo bar… quux

What I'd like to see instead is:

1   2   3
foo bar
    baz
    qux quux

I've made a quick prototype, changing the tabulated-list-print-col
function to handle multiline strings:

From 583367791aa6f2f87984331f370be01dcba31971 Mon Sep 17 00:00:00 2001
From: Andrey Listopadov <andreyorst <at> gmail.com>
Date: Sun, 2 Jun 2024 15:54:52 +0300
Subject: [PATCH] preserve column offset when printing multiline strings

---
 lisp/emacs-lisp/tabulated-list.el | 30 +++++++++++++++++++++++++-----
 1 file changed, 25 insertions(+), 5 deletions(-)

diff --git a/lisp/emacs-lisp/tabulated-list.el b/lisp/emacs-lisp/tabulated-list.el
index c86e3f9c5df..3e24c823f9e 100644
--- a/lisp/emacs-lisp/tabulated-list.el
+++ b/lisp/emacs-lisp/tabulated-list.el
@@ -608,8 +608,16 @@ tabulated-list-print-col
     ;; and has some space left, truncate to `available-space' instead.
     (when (and not-last-col
 	       (> label-width available-space))
-      (setq label (truncate-string-to-width
-		   label available-space nil nil t t)
+      (setq label
+            (if (string-match-p "\n" label)
+                (string-join
+                 (mapcar (lambda (row)
+                           (truncate-string-to-width
+	                    row available-space nil nil t t))
+                         (string-split label "\n"))
+                 "\n")
+              (truncate-string-to-width
+	       label available-space nil nil t t))
 	    label-width available-space))
     (setq label (bidi-string-mark-left-to-right label))
     (when (and right-align (> width label-width))
@@ -619,9 +627,21 @@ tabulated-list-print-col
         (setq width (- width shift))
         (setq x (+ x shift))))
     (cond ((stringp col-desc)
-           (insert (if (get-text-property 0 'help-echo label)
-                       label
-                     (propertize label 'help-echo help-echo))))
+           (let ((label (if (string-match-p "\n" label)
+                            (string-replace
+                             "\n"
+                             (concat
+                              "\n"
+                              (make-string (save-mark-and-excursion
+                                             (let ((pos (point)))
+                                               (beginning-of-line)
+                                               (- pos (point))))
+                                           (string-to-char " ")))
+                             label)
+                          label)))
+             (insert (if (get-text-property 0 'help-echo label)
+                         label
+                       (propertize label 'help-echo help-echo)))))
           ((eq (car col-desc) 'image)
            (insert (propertize " "
                                'display col-desc
--
2.44.0

It handles truncation on per-line basis, and pads the string in a
probably wrong way (I don't know how it should work with right padding
and all)..

There's probably a better way of doing it though, and if possible I'd
like to preserver columns following that on the same line as other
columns. I.e. instead of

1   2   3
foo bar
    baz
    qux quux

I'd like to see

1   2   3
foo bar quux
    baz
    qux

The patch above is merely a POC, mayve someone with better elisp skills
and knowledge of tabulated-list-mode would be able to tackle this problem?



In GNU Emacs 30.0.50 (build 1, x86_64-pc-linux-gnu, GTK+ Version
 3.24.41, cairo version 1.17.8) of 2024-05-12 built on toolbox
Repository revision: dcb6a9ebcbf92a4ca7c0e2c393d7a8dd9b1d351e
Repository branch: master
System Description: Fedora Linux 38 (Container Image)

Configured using:
 'configure --without-compress-install --with-native-compilation=yes
 --with-pgtk --with-mailutils --with-xwidgets
 --prefix=/var/home/alist/.local'

Configured features:
ACL CAIRO DBUS FREETYPE GIF GLIB GMP GNUTLS GPM GSETTINGS HARFBUZZ JPEG
LCMS2 LIBOTF LIBSELINUX LIBXML2 MODULES NATIVE_COMP NOTIFY INOTIFY
PDUMPER PGTK PNG RSVG SECCOMP SOUND SQLITE3 THREADS TIFF
TOOLKIT_SCROLL_BARS TREE_SITTER XIM XWIDGETS GTK3 ZLIB

Important settings:
  value of $LANG: en_US.UTF-8
  locale-coding-system: utf-8-unix

Major mode: ELisp/d

Minor modes in effect:
  bug-reference-prog-mode: t
  csv-field-index-mode: t
  global-git-commit-mode: t
  magit-auto-revert-mode: t
  outline-minor-mode: t
  electric-pair-mode: t
  isayt-mode: t
  savehist-mode: t
  delete-selection-mode: t
  pixel-scroll-precision-mode: t
  global-auto-revert-mode: t
  repeat-mode: t
  vertico-mode: t
  marginalia-mode: t
  corfu-popupinfo-mode: t
  global-corfu-mode: t
  corfu-mode: t
  global-region-bindings-mode: t
  recentf-mode: t
  server-mode: t
  common-lisp-modes-mode: t
  override-global-mode: t
  puni-mode: t
  tooltip-mode: t
  global-eldoc-mode: t
  eldoc-mode: t
  show-paren-mode: t
  electric-indent-mode: t
  mouse-wheel-mode: t
  menu-bar-mode: t
  file-name-shadow-mode: t
  context-menu-mode: t
  global-font-lock-mode: t
  font-lock-mode: t
  blink-cursor-mode: t
  minibuffer-regexp-mode: 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
  hs-minor-mode: t

Load-path shadows:
/var/home/alist/.config/emacs/elpa/transient-20240509.1849/transient hides /var/home/alist/.local/share/emacs/30.0.50/lisp/transient
/var/home/alist/.config/emacs/elpa/modus-themes-20240505.331/theme-loaddefs hides /var/home/alist/.local/share/emacs/30.0.50/lisp/theme-loaddefs

Features:
(shadow mail-extr mailalias rmail emacsbug whitespace dired-aux
magit-patch bug-reference etags fileloop flyspell ispell org-element
org-persist org-id org-refile avl-tree generator oc-basic ol-eww eww
url-queue mm-url ol-rmail ol-mhe ol-irc ol-info ol-gnus nnselect
gnus-art mm-uu mml2015 mm-view mml-smime smime 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 gnus-win gnus nnheader range
ol-docview doc-view jka-compr image-mode exif ol-bibtex bibtex ol-bbdb
ol-w3m ol-doi org-link-doi org-tempo tempo ob-clojure ob-fennel
fennel-proto-repl fennel-mode inf-lisp ob-lua ob-shell 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 org-version ob-emacs-lisp
ob-core ob-eval org-cycle org-table ol org-fold org-fold-core org-keys
oc org-loaddefs cal-menu calendar cal-loaddefs org-compat org-macs
vtable edebug tabify csv csv-autoloads loaddefs-gen tar-mode mm-archive
gnutls network-stream url-cache url-http url-auth url-gw nsm cl-print
debug backtrace vc-git find-func shortdoc puni consult magit-bookmark
bookmark display-line-numbers help-fns radix-tree mule-util csv-mode
sort cus-start clj-refactor cap-words superword subword hydra lv
inflections mc-hide-unmatched-lines-mode mc-mark-more sgml-mode facemenu
mc-cycle-cursors multiple-cursors-core advice rect paredit yasnippet
cider tramp-sh cider-debug cider-browse-ns cider-mode cider-xref-backend
cider-find cider-inspector cider-completion cider-profile cider-eval
cider-jar arc-mode archive-mode cider-repl-history pulse cider-repl
cider-resolve cider-test cider-overlays cider-stacktrace cider-doc
cider-browse-spec cider-clojuredocs cider-eldoc cider-docstring shr
pixel-fill kinsoku url-file svg dom cider-client cider-common xref
cider-completion-context cider-connection cider-popup sesman-browser
nrepl-client cider-util color tramp trampver tramp-integration files-x
tramp-message tramp-compat xdg parse-time iso8601 tramp-loaddefs sesman
vc vc-dispatcher queue nrepl-dict spinner parseedn parseclj-parser
parseclj-lex parseclj-alist clojure-mode lisp-mnt align thingatpt
misearch multi-isearch clojure-compilation-mode compile face-remap
magit-extras vertico-directory orderless magit-submodule magit-blame
magit-stash magit-reflog magit-bisect magit-push magit-pull magit-fetch
magit-clone magit-remote magit-commit magit-sequence magit-notes
magit-worktree magit-tag magit-merge magit-branch magit-reset
magit-files magit-refs magit-status magit magit-repos magit-apply
magit-wip magit-log which-func imenu magit-diff smerge-mode diff
diff-mode track-changes git-commit log-edit message sendmail yank-media
puny rfc822 mml mml-sec epa derived epg rfc6068 epg-config gnus-util
text-property-search time-date mm-decode mm-bodies mm-encode mail-parse
rfc2231 rfc2047 rfc2045 mm-util ietf-drums mail-prsvr mailabbrev
mail-utils gmm-utils mailheader pcvs-util add-log magit-core
magit-autorevert magit-margin magit-transient magit-process with-editor
shell pcomplete comint ansi-osc ansi-color magit-mode transient
magit-git magit-base magit-section format-spec cursor-sensor crm project
noutline outline elec-pair isayt hideshow savehist delsel pixel-scroll
cua-base ring autorevert filenotify repeat vertico marginalia
corfu-popupinfo cape corfu compat region-bindings recentf tree-widget
init gnome-proxy gsettings s gvariant parsec dash server lua-prettify
json-hs-extra treesit indirect-narrow dired dired-loaddefs
use-package-delight modus-vivendi-tritanopia-theme
modus-operandi-tritanopia-theme modus-vivendi-deuteranopia-theme
modus-operandi-deuteranopia-theme modus-vivendi-tinted-theme
modus-operandi-tinted-theme modus-vivendi-theme modus-operandi-theme
modus-themes dbus xml common-lisp-modes novice cus-edit pp cus-load
wid-edit font mode-line defaults edmacro kmacro functions
use-package-bind-key bind-key local-config delight comp comp-cstr
warnings comp-run comp-common rx use-package-ensure cl-extra help-mode
use-package-core early-init finder-inf blog-autoloads cape-autoloads
clj-decompiler-autoloads clj-refactor-autoloads cider-autoloads
clojure-mode-autoloads common-lisp-modes-autoloads consult-autoloads
corfu-terminal-autoloads corfu-autoloads csv-mode-autoloads
delight-autoloads eat-autoloads expand-region-autoloads
fennel-mode-autoloads gnome-proxy-autoloads gsettings-autoloads
gvariant-autoloads infinite-autoloads inflections-autoloads
isayt-autoloads jdecomp-autoloads lsp-java-autoloads
lsp-metals-autoloads dap-mode-autoloads lsp-docker-autoloads
bui-autoloads lsp-treemacs-autoloads lsp-mode-autoloads f-autoloads
marginalia-autoloads markdown-mode-autoloads
message-view-patch-autoloads magit-autoloads pcase
magit-section-autoloads git-commit-autoloads modus-themes-autoloads
mu4e-alert-autoloads alert-autoloads log4e-autoloads gntp-autoloads
multiple-cursors-autoloads orderless-autoloads ov-autoloads
ox-hugo-autoloads paredit-autoloads parsec-autoloads parseedn-autoloads
parseclj-autoloads phi-search-autoloads popon-autoloads puni-autoloads
easy-mmode queue-autoloads racket-mode-autoloads
region-bindings-autoloads request-autoloads scala-mode-autoloads
separedit-autoloads edit-indirect-autoloads sesman-autoloads
spinner-autoloads sql-indent-autoloads tomelr-autoloads
transient-autoloads treemacs-autoloads cfrs-autoloads posframe-autoloads
ht-autoloads hydra-autoloads lv-autoloads pfuture-autoloads
ace-window-autoloads avy-autoloads s-autoloads dash-autoloads
vertico-autoloads vundo-autoloads info with-editor-autoloads
yaml-autoloads yaml-mode-autoloads yasnippet-autoloads
zig-mode-autoloads reformatter-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 icons password-cache json
subr-x map byte-opt gv bytecomp byte-compile url-vars cl-loaddefs cl-lib
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 xwidget-internal dbusbind inotify dynamic-setting
system-font-setting font-render-setting cairo gtk pgtk lcms2 multi-tty
move-toolbar make-network-process native-compile emacs)

Memory information:
((conses 16 1161598 294352) (symbols 48 63695 6)
 (strings 32 336047 7960) (string-bytes 1 10612200)
 (vectors 16 113623) (vector-slots 8 2104398 91480)
 (floats 8 1081 3104) (intervals 56 25909 3309) (buffers 992 38))

--
Andrey Listopadov




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#71325; Package emacs. (Mon, 03 Jun 2024 07:05:02 GMT) Full text and rfc822 format available.

Message #8 received at 71325 <at> debbugs.gnu.org (full text, mbox):

From: Andrey Listopadov <andreyorst <at> gmail.com>
To: 71325 <at> debbugs.gnu.org
Subject: RE: 30.0.50; multiline entries in tabulated-lists are left-aligned
Date: Mon, 3 Jun 2024 09:54:06 +0300 (GMT+03:00)
Additional info. With the solution above, if there are multiple multiline 
columns the result will be like a staircase:

1   2   3    4
foo
bar baz
    qux quux
        quuz quuuz

Instead, I'd expect it to be displayed as

1   2   3    3
foo baz quux quuuz
bar qux quuz

However, I couldn't find a proper way of keeping the vertical position 
while inserting columns.

P.S. I don't seem to get the acknowledgement mail in my inbox, neither in 
the spam folder. I see the Acknowledgement Sent message on the tracker 
though. Did something break with gmail?




This bug report was last modified 136 days ago.

Previous Next


GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.