Skip to content

Commit b8344d5

Browse files
authored
fix kotl mode delete char with active region (#842)
1 parent b14310d commit b8344d5

File tree

3 files changed

+285
-68
lines changed

3 files changed

+285
-68
lines changed

ChangeLog

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,16 @@
1+
2026-01-19 Mats Lidell <matsl@gnu.org>
2+
3+
* test/kotl-mode-tests.el (kotl-mode--delete-region)
4+
(kotl-mode--delete-char): Add tests.
5+
6+
* kotl/kotl-mode.el (kotl-mode:delete-char-acc): Accumulate deleted chars
7+
to setup kill-ring.
8+
(kotl-mode:delete-char, kotl-mode:delete-backward-char): Fix
9+
inconsistencies with delete-char - Support transient mark mode. Use
10+
kotl-mode:delete-char-acc for saving multiple chars to kill-ring when
11+
called with kill-flag. (The latter is implicit when used interactively
12+
with a prefix arg.)
13+
114
2026-01-07 Mats Lidell <matsl@gnu.org>
215

316
* hywiki.el (hywiki-mode): Remove arg value :toggle, not an alternative to

kotl/kotl-mode.el

Lines changed: 103 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
;; Author: Bob Weiner
44
;;
55
;; Orig-Date: 6/30/93
6-
;; Last-Mod: 1-Jan-26 at 18:18:27 by Mats Lidell
6+
;; Last-Mod: 19-Jan-26 at 22:34:04 by Mats Lidell
77
;;
88
;; SPDX-License-Identifier: GPL-3.0-or-later
99
;;
@@ -446,14 +446,17 @@ With optional prefix arg DELETE-FLAG, delete region."
446446
Return number of characters deleted.
447447
Optional KILL-FLAG non-nil means save in kill ring instead of deleting.
448448
Do not delete across cell boundaries."
449-
(interactive "*P")
450-
(when (called-interactively-p 'interactive)
451-
(when current-prefix-arg
452-
(setq kill-flag t
453-
arg (prefix-numeric-value current-prefix-arg))))
454-
(unless arg
455-
(setq arg 1))
456-
(kotl-mode:delete-char (- arg) kill-flag))
449+
(interactive "*p\nP")
450+
(cond ((and (use-region-p)
451+
delete-active-region
452+
(= arg 1))
453+
;; If a region is active, kill or delete it.
454+
(if (or kill-flag
455+
(eq delete-active-region 'kill))
456+
(kotl-mode:kill-region (region-beginning) (region-end))
457+
(kotl-mode:delete-region (region-beginning) (region-end))))
458+
(t
459+
(kotl-mode:delete-char (- arg) kill-flag))))
457460

458461
(defun kotl-mode:delete-blank-lines ()
459462
"On blank line in a cell, delete all surrounding blank lines, leaving just one.
@@ -478,69 +481,95 @@ whitespace at the end of the cell."
478481
(delete-region (max start (point)) end)))
479482
(kotl-mode:to-valid-position))
480483

484+
(defvar kotl-mode:delete-char-acc nil
485+
"Accumulate deleted chars to populate `kill-ring'.")
486+
487+
(defun kotl-mode:delete-char-acc (arg kill-flag)
488+
"Delete one character and accumulate in the kill ring.
489+
Deletes (forward if ARG > 0, backward if ARG < 0).
490+
First call creates a new kill ring entry, subsequent calls appends.
491+
With KILL-FLAG nil just call `delete-char'."
492+
(if (not kill-flag)
493+
(delete-char arg)
494+
(let ((char (char-to-string (if (< arg 0)
495+
(char-before)
496+
(char-after)))))
497+
(delete-char arg)
498+
(if kotl-mode:delete-char-acc
499+
(kill-append char (< arg 0))
500+
(kill-new char)
501+
(setq kotl-mode:delete-char-acc t)))))
502+
481503
(defun kotl-mode:delete-char (arg &optional kill-flag)
482504
"Delete up to prefix ARG characters following point.
483505
Return number of characters deleted.
484506
Optional KILL-FLAG non-nil means save in kill ring instead of deleting.
485507
Do not delete across cell boundaries."
486-
(interactive "*P")
487-
(when (called-interactively-p 'interactive)
488-
(when current-prefix-arg
489-
(setq kill-flag t
490-
arg (prefix-numeric-value current-prefix-arg))))
491-
(unless arg
492-
(setq arg 1))
493-
494-
(if (not (and (boundp 'kotl-kview) (kview:is-p kotl-kview)))
495-
;; Support use within Org tables outside of the Koutliner
496-
(delete-char arg kill-flag)
497-
(let ((del-count 0)
498-
(indent (kcell-view:indent))
499-
count start end)
500-
(cond ((> arg 0)
501-
(if (kotl-mode:eocp)
502-
(error "(kotl-mode:delete-char): End of cell")
503-
(setq end (kcell-view:end)
504-
arg (min arg (- end (point))))
505-
(while (and (> arg 0) (not (kotl-mode:eocp)))
506-
(if (kotl-mode:eolp)
507-
(if (not (eq ?\ (char-syntax (following-char))))
508-
(setq arg 0
509-
del-count (1- del-count))
510-
(delete-char 1 kill-flag)
511-
;; There may be non-whitespace characters in the
512-
;; indent area. Don't delete them.
513-
(setq count indent)
514-
(while (and (> count 0)
515-
(eq ?\ (char-syntax (following-char))))
516-
(delete-char 1)
517-
(setq count (1- count))))
518-
(delete-char 1 kill-flag))
519-
(setq arg (1- arg)
520-
del-count (1+ del-count)))))
521-
((< arg 0)
522-
(if (kotl-mode:bocp)
523-
(error "(kotl-mode:delete-char): Beginning of cell")
524-
(setq start (kcell-view:start)
525-
arg (max arg (- start (point))))
526-
(while (and (< arg 0) (not (kotl-mode:bocp)))
527-
(if (kotl-mode:bolp)
528-
(if (not (eq ?\ (char-syntax (preceding-char))))
529-
(setq arg 0
530-
del-count (1- del-count))
531-
;; There may be non-whitespace characters in the
532-
;; indent area. Don't delete them.
533-
(setq count indent)
534-
(while (and (> count 0)
535-
(eq ?\ (char-syntax (preceding-char))))
536-
(delete-char -1)
537-
(setq count (1- count)))
538-
(if (zerop count)
539-
(delete-char -1 kill-flag)))
540-
(delete-char -1 kill-flag))
541-
(setq arg (1+ arg)
542-
del-count (1+ del-count))))))
543-
del-count)))
508+
(interactive "*p\nP")
509+
(unless (integerp arg)
510+
(signal 'wrong-type-argument (list 'integerp arg)))
511+
(cond ((and (use-region-p)
512+
delete-active-region
513+
(= arg 1))
514+
;; If a region is active, kill or delete it.
515+
(if (or kill-flag
516+
(eq delete-active-region 'kill))
517+
(kotl-mode:kill-region (region-beginning) (region-end))
518+
(kotl-mode:delete-region (region-beginning) (region-end))))
519+
(t
520+
(if (not (and (boundp 'kotl-kview) (kview:is-p kotl-kview)))
521+
;; Support use within Org tables outside of the Koutliner
522+
(delete-char arg kill-flag)
523+
(let ((del-count 0)
524+
(indent (kcell-view:indent))
525+
count start end
526+
kotl-mode:delete-char-acc)
527+
(cl-flet ((delete-char (arg &optional kill-flag)
528+
(kotl-mode:delete-char-acc arg kill-flag)))
529+
(cond ((> arg 0)
530+
(if (kotl-mode:eocp)
531+
(error "(kotl-mode:delete-char): End of cell")
532+
(setq end (kcell-view:end)
533+
arg (min arg (- end (point))))
534+
(while (and (> arg 0) (not (kotl-mode:eocp)))
535+
(if (kotl-mode:eolp)
536+
(if (not (eq ?\ (char-syntax (following-char))))
537+
(setq arg 0
538+
del-count (1- del-count))
539+
(delete-char 1 kill-flag)
540+
;; There may be non-whitespace characters in the
541+
;; indent area. Don't delete them.
542+
(setq count indent)
543+
(while (and (> count 0)
544+
(eq ?\ (char-syntax (following-char))))
545+
(delete-char 1)
546+
(setq count (1- count))))
547+
(delete-char 1 kill-flag))
548+
(setq arg (1- arg)
549+
del-count (1+ del-count)))))
550+
((< arg 0)
551+
(if (kotl-mode:bocp)
552+
(error "(kotl-mode:delete-char): Beginning of cell")
553+
(setq start (kcell-view:start)
554+
arg (max arg (- start (point))))
555+
(while (and (< arg 0) (not (kotl-mode:bocp)))
556+
(if (kotl-mode:bolp)
557+
(if (not (eq ?\ (char-syntax (preceding-char))))
558+
(setq arg 0
559+
del-count (1- del-count))
560+
;; There may be non-whitespace characters in the
561+
;; indent area. Don't delete them.
562+
(setq count indent)
563+
(while (and (> count 0)
564+
(eq ?\ (char-syntax (preceding-char))))
565+
(delete-char -1)
566+
(setq count (1- count)))
567+
(if (zerop count)
568+
(delete-char -1 kill-flag)))
569+
(delete-char -1 kill-flag))
570+
(setq arg (1+ arg)
571+
del-count (1+ del-count)))))))
572+
del-count)))))
544573

545574
(defun kotl-mode:delete-horizontal-space ()
546575
"Delete all spaces and tabs around point."
@@ -797,6 +826,13 @@ If a completion is active, this aborts the completion only."
797826
((mark t)
798827
(indicate-copied-region)))))))
799828

829+
(defun kotl-mode:delete-region (start end)
830+
"Delete region between START and END within a single kcell.
831+
Delegates to `kotl-mode:kill-region' but does not store killed text in
832+
`kill-ring'."
833+
(let (kill-ring kill-ring-yank-pointer)
834+
(kotl-mode:kill-region start end)))
835+
800836
(defun kotl-mode:kill-or-copy-region (start end copy-flag &optional kill-str)
801837
(when (and start end)
802838
(let ((indent (kcell-view:indent))

0 commit comments

Comments
 (0)