Subject: 29.4; `backward-delete-char-untabify': active-region behavior
From: Asher Copeland <[email-masked]>
To: [email-masked]
Date: Sun, 22 Dec 2024 17:52:04 -0800
List-Id: <debbugs-submit.debbugs.gnu.org>

The documentation of `backward-delete-char-untabify' indicates the
following:

 If Transient Mark mode is enabled, the mark is active, and ARG is 1,
 delete the text in the region and deactivate the mark instead.
 To disable this, set option `delete-active-region' to nil.

However, when `backward-delete-char-untabify-method' is set to hungry or
all and point has more than one whitespace character before it
(i.e. that `backward-delete-char-untabify' would delete more than one
character), `backward-delete-char-untabify' ignores the settings of
`transient-mark-mode' and `delete-active-region' and proceeds with its
normal action.

Practically, this means that, in a snippet of text such as the
following (assuming the spacing/newlines don't get messed up):

    line1
    line2
    line3

If point were placed before line2 and the region is active and nonempty,
with `backward-delete-char-untabify-method' set to hungry, the expected
behavior (and the behavior that is currently documented) would be that
the text highlighted by the region would be deleted and that the region
would be deactivated. What the function would instead do is delete the
spaces to the left of point and deactivate the region.

I have found this issue to occur running under `emacs -Q'.

For consistency with the current documentation and other deletion
commands, I believe that the behavior of `backward-delete-char-untabify'
should change to delete the text in the region, under the same
conditions that `backward-delete-char' would do the same.

Here is the last form of the definition of
`backward-delete-char-untabify', from simple.el:6522, for reference:

   (let* ((skip (cond ((eq backward-delete-char-untabify-method 'hungry) " \t")
                      ((eq backward-delete-char-untabify-method 'all)
                       " \t\n\r")))
          (n (if skip
                 (let* ((oldpt (point))
                        (wh (- oldpt (save-excursion
                                       (skip-chars-backward skip)
                                       (constrain-to-field nil oldpt)))))
                   (+ arg (if (zerop wh) 0 (1- wh))))
               arg)))
     ;; Avoid warning about delete-backward-char
     (with-no-warnings (delete-backward-char n killp))))

The issue seems to stem from the last line. In the described conditions,
the symbol `n' would be bound to a value greater than 1. Therefore,
`delete-backward-char' would delete n characters and deactivate the
region, instead of deleting the region.

--
Asher

In GNU Emacs 29.4 (build 1, x86_64-pc-linux-gnu, X toolkit, cairo
 version 1.18.0, Xaw scroll bars) of 2024-10-16 built on asher-v-ubuntu
System Description: Ubuntu 24.04.1 LTS

Configured using:
 'configure --with-x-toolkit=lucid --prefix=/opt/emacs'

Configured features:
CAIRO DBUS FREETYPE GIF GLIB GMP GNUTLS GSETTINGS HARFBUZZ JPEG
LIBSELINUX LIBXML2 MODULES NOTIFY INOTIFY PDUMPER PNG RSVG SECCOMP SOUND
THREADS TIFF TOOLKIT_SCROLL_BARS TREE_SITTER WEBP X11 XDBE XIM XINPUT2
XPM LUCID ZLIB

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

Major mode: Fundamental

Minor modes in effect:
  gpm-mouse-mode: t
  tooltip-mode: t
  global-eldoc-mode: t
  show-paren-mode: t
  electric-indent-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
  blink-cursor-mode: t
  line-number-mode: t
  indent-tabs-mode: t
  transient-mark-mode: t
  auto-composition-mode: linux
  auto-encryption-mode: t
  auto-compression-mode: t

Load-path shadows:
None found.

Features:
(shadow sort mail-extr help-fns radix-tree help-mode emacsbug message
mailcap yank-media puny dired dired-loaddefs rfc822 mml mml-sec
password-cache epa derived epg rfc6068 epg-config gnus-util
text-property-search time-date subr-x mm-decode mm-bodies mm-encode
mail-parse rfc2231 mailabbrev gmm-utils mailheader cl-loaddefs cl-lib
sendmail rfc2047 rfc2045 ietf-drums mm-util mail-prsvr mail-utils
t-mouse term/linux rmc iso-transl tooltip cconv eldoc paren electric
uniquify ediff-hook vc-hooks lisp-float-type elisp-mode mwheel
term/x-win x-win term/common-win x-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 x-toolkit
xinput2 x multi-tty make-network-process emacs)

Memory information:
((conses 16 38095 7179)
 (symbols 48 5293 1)
 (strings 32 13493 2007)
 (string-bytes 1 379725)
 (vectors 16 7691)
 (vector-slots 8 105658 7932)
 (floats 8 19 318)
 (intervals 56 201 9)
 (buffers 984 11))