commit 8816b4f342983468d49f93decf216151e9c6ffbc (HEAD, refs/remotes/origin/master) Author: Juri Linkov Date: Thu Sep 19 09:14:34 2024 +0300 * lisp/dired-aux.el (dired-do-open): Optimize (bug#73004). Detect system-type only once, then iterate over files for every system type separately. diff --git a/lisp/dired-aux.el b/lisp/dired-aux.el index 1d0e29b8782..15bd5c407b9 100644 --- a/lisp/dired-aux.el +++ b/lisp/dired-aux.el @@ -1470,17 +1470,21 @@ system is determined by `shell-command-guess-open'." (equal command "start")) (setq command "open")) (if command - (dolist (file files) - (cond - ((memq system-type '(ms-dos)) - (shell-command (concat command " " (shell-quote-argument file)))) - ((memq system-type '(windows-nt)) - (w32-shell-execute command (convert-standard-filename file))) - ((memq system-type '(cygwin)) - (call-process command nil nil nil file)) - ((memq system-type '(darwin)) - (start-process (concat command " " file) nil command file)) - (t + (cond + ((memq system-type '(ms-dos)) + (dolist (file files) + (shell-command (concat command " " (shell-quote-argument file))))) + ((memq system-type '(windows-nt)) + (dolist (file files) + (w32-shell-execute command (convert-standard-filename file)))) + ((memq system-type '(cygwin)) + (dolist (file files) + (call-process command nil nil nil file))) + ((memq system-type '(darwin)) + (dolist (file files) + (start-process (concat command " " file) nil command file))) + (t + (dolist (file files) (call-process command nil 0 nil file)))) (error "Open not supported on this system")))) commit ae4171efdc60dfa53aa404e5926f5165dbf98d59 Author: Spencer Baugh Date: Thu Oct 12 18:01:46 2023 -0400 Support numeric indexing in let-alist let-alist is very useful. But sometimes an alist contains a list in the middle, which contains yet more alists. Previously, this was somewhat painful to deal with, and required something like: (let-alist alist (let-alist (nth 0 .a) (let-alist (nth 3 .b) .c))) Now, the following works: (let-alist alist .a.0.b.3.c) * lisp/emacs-lisp/let-alist.el (let-alist--access-sexp): Properly parse numbers to handle lists. (Bug#66509) (let-alist--list-to-sexp): Use nth to handle numbers. (let-alist): Update docs. diff --git a/lisp/emacs-lisp/let-alist.el b/lisp/emacs-lisp/let-alist.el index cdd476d9df6..b1822519999 100644 --- a/lisp/emacs-lisp/let-alist.el +++ b/lisp/emacs-lisp/let-alist.el @@ -36,22 +36,23 @@ ;; symbol inside body is let-bound to their cdrs in the alist. Dotted ;; symbol is any symbol starting with a `.'. Only those present in ;; the body are let-bound and this search is done at compile time. +;; A number will result in a list index. ;; ;; For instance, the following code ;; ;; (let-alist alist -;; (if (and .title .body) +;; (if (and .title.0 .body) ;; .body ;; .site ;; .site.contents)) ;; ;; essentially expands to ;; -;; (let ((.title (cdr (assq 'title alist))) +;; (let ((.title.0 (nth 0 (cdr (assq 'title alist)))) ;; (.body (cdr (assq 'body alist))) ;; (.site (cdr (assq 'site alist))) ;; (.site.contents (cdr (assq 'contents (cdr (assq 'site alist)))))) -;; (if (and .title .body) +;; (if (and .title.0 .body) ;; .body ;; .site ;; .site.contents)) @@ -93,14 +94,17 @@ symbol, and each cdr is the same symbol without the `.'." (if (string-match "\\`\\." name) clean (let-alist--list-to-sexp - (mapcar #'intern (nreverse (split-string name "\\."))) + (mapcar #'read (nreverse (split-string name "\\."))) variable)))) (defun let-alist--list-to-sexp (list var) "Turn symbols LIST into recursive calls to `cdr' `assq' on VAR." - `(cdr (assq ',(car list) - ,(if (cdr list) (let-alist--list-to-sexp (cdr list) var) - var)))) + (let ((sym (car list)) + (rest (if (cdr list) (let-alist--list-to-sexp (cdr list) var) + var))) + (cond + ((numberp sym) `(nth ,sym ,rest)) + (t `(cdr (assq ',sym ,rest)))))) (defun let-alist--remove-dot (symbol) "Return SYMBOL, sans an initial dot." @@ -116,22 +120,23 @@ symbol, and each cdr is the same symbol without the `.'." "Let-bind dotted symbols to their cdrs in ALIST and execute BODY. Dotted symbol is any symbol starting with a `.'. Only those present in BODY are let-bound and this search is done at compile time. +A number will result in a list index. For instance, the following code (let-alist alist - (if (and .title .body) + (if (and .title.0 .body) .body .site .site.contents)) essentially expands to - (let ((.title (cdr (assq \\='title alist))) + (let ((.title (nth 0 (cdr (assq \\='title alist)))) (.body (cdr (assq \\='body alist))) (.site (cdr (assq \\='site alist))) (.site.contents (cdr (assq \\='contents (cdr (assq \\='site alist)))))) - (if (and .title .body) + (if (and .title.0 .body) .body .site .site.contents)) commit 252ed22d62fc80e2af6f37cf55c62848f6bc8e29 Author: Eli Zaretskii Date: Wed Sep 18 21:22:04 2024 +0300 ; Use c-ctype.h in w32*.c * src/w32.c: * src/w32fns.c: Replace ctype.h functions by equivalent c-ctype.h functions. diff --git a/src/w32.c b/src/w32.c index cec15606bf2..05f0ebf396e 100644 --- a/src/w32.c +++ b/src/w32.c @@ -32,7 +32,6 @@ along with GNU Emacs. If not, see . */ #include #include #include -#include #include #include #include /* must be before nt/inc/sys/time.h, for MinGW64 */ @@ -264,6 +263,7 @@ typedef struct _REPARSE_DATA_BUFFER { #include +#include #include #include /* for fdutimens */ @@ -2558,7 +2558,7 @@ parse_root (const char * name, const char ** pPath) return 0; /* find the root name of the volume if given */ - if (isalpha (name[0]) && name[1] == ':') + if (c_isalpha (name[0]) && name[1] == ':') { /* skip past drive specifier */ name += 2; @@ -3311,7 +3311,7 @@ static BOOL fixed_drives[26]; at least for non-local drives. Info for fixed drives is never stale. */ #define DRIVE_INDEX( c ) ( (c) <= 'Z' ? (c) - 'A' : (c) - 'a' ) #define VOLINFO_STILL_VALID( root_dir, info ) \ - ( ( isalpha (root_dir[0]) && \ + ( ( c_isalpha (root_dir[0]) && \ fixed_drives[ DRIVE_INDEX (root_dir[0]) ] ) \ || GetTickCount () - info->timestamp < 10000 ) @@ -3380,7 +3380,7 @@ GetCachedVolumeInformation (char * root_dir) involve network access, and so is extremely quick). */ /* Map drive letter to UNC if remote. */ - if (isalpha (root_dir[0]) && !fixed[DRIVE_INDEX (root_dir[0])]) + if (c_isalpha (root_dir[0]) && !fixed[DRIVE_INDEX (root_dir[0])]) { char remote_name[ 256 ]; char drive[3] = { root_dir[0], ':' }; @@ -3595,9 +3595,9 @@ map_w32_filename (const char * name, const char ** pPath) default: if ( left && 'A' <= c && c <= 'Z' ) { - *str++ = tolower (c); /* map to lower case (looks nicer) */ + *str++ = c_tolower (c); /* map to lower case (looks nicer) */ left--; - dots = 0; /* started a path component */ + dots = 0; /* started a path component */ } break; } diff --git a/src/w32fns.c b/src/w32fns.c index bd65aa48a14..0a3f5c38a58 100644 --- a/src/w32fns.c +++ b/src/w32fns.c @@ -937,13 +937,13 @@ x_to_w32_color (const char * colorname) { int len = strlen (colorname); - if (isdigit (colorname[len - 1])) + if (c_isdigit (colorname[len - 1])) { char *ptr, *approx = alloca (len + 1); strcpy (approx, colorname); ptr = &approx[len - 1]; - while (ptr > approx && isdigit (*ptr)) + while (ptr > approx && c_isdigit (*ptr)) *ptr-- = '\0'; ret = w32_color_map_lookup (approx); @@ -3725,7 +3725,7 @@ post_character_message (HWND hwnd, UINT msg, message that has no particular effect. */ { int c = wParam; - if (isalpha (c) && wmsg.dwModifiers == ctrl_modifier) + if (c_isalpha (c) && wmsg.dwModifiers == ctrl_modifier) c = make_ctrl_char (c) & 0377; if (c == quit_char || (wmsg.dwModifiers == 0 @@ -8748,7 +8748,7 @@ lookup_vk_code (char *key) || (key[0] >= '0' && key[0] <= '9')) return key[0]; if (key[0] >= 'a' && key[0] <= 'z') - return toupper(key[0]); + return c_toupper (key[0]); } } @@ -9518,7 +9518,7 @@ DEFUN ("file-system-info", Ffile_system_info, Sfile_system_info, 1, 1, 0, BOOL result; /* find the root name of the volume if given */ - if (isalpha (name[0]) && name[1] == ':') + if (c_isalpha (name[0]) && name[1] == ':') { rootname[0] = name[0]; rootname[1] = name[1]; commit 03a991931863486436193f3e8edd0fd7d7d271c3 Author: Juri Linkov Date: Wed Sep 18 20:37:44 2024 +0300 Additional fix for kill-region-dwim (bug#69097) * lisp/simple.el (kill-region): Restore the original logic of raising the error unless both 'beg' and 'end' are non-nil since 'end' is always non-nil. diff --git a/lisp/simple.el b/lisp/simple.el index fcdf644d9d9..4fff24205be 100644 --- a/lisp/simple.el +++ b/lisp/simple.el @@ -5870,7 +5870,7 @@ Supply two arguments, character positions BEG and END indicating the (cond ((and kill-region-dwim (not (use-region-p))) (list beg end kill-region-dwim)) - ((not (or beg end)) + ((not (and beg end)) (user-error "The mark is not set now, so there is no region")) ((list beg end 'region)))))) commit 9026bfb5716de7a6d8ea5df60da942204c32feff Author: Juri Linkov Date: Wed Sep 18 20:20:19 2024 +0300 More fixes for kill-region-dwim (bug#69097) * lisp/simple.el (kill-region-dwim): Move the default nil to the top of choices. (kill-region): Set the FORCE argument of 'mark' to non-nil if kill-region-dwim is non-nil. That allows everyone to use non-nil kill-region-dwim even if mark-even-if-inactive is nil. Don't check 'last-command' if kill-region-dwim is non-nil. That allows everyone to type C-w twice in a row to delete two previous words. diff --git a/etc/NEWS b/etc/NEWS index 8bd5c7c9515..b52ad001a2e 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -142,7 +142,7 @@ you to bind keys to operate more similarly to the terminal. --- ** New user option 'kill-region-dwim'. This option, if non-nil, modifies the fall-back behavior of -'kill-region' if no region is active, and will kill the last word +'kill-region' ('C-w') if no region is active, and will kill the last word instead of raising an error. Note that if you have disabled Transient Mark mode you might prefer to use 'unix-word-rubout', as this feature relies on there being an active region. diff --git a/lisp/simple.el b/lisp/simple.el index 9fbd9bfb577..fcdf644d9d9 100644 --- a/lisp/simple.el +++ b/lisp/simple.el @@ -5825,9 +5825,9 @@ If set to `emacs-word', kill the last word as defined by the current major mode. If set to `unix-word', kill the last word in the style of a shell like Bash. This ignores the major mode like `unix-word-rubout' (which see)." - :type '(choice (const :tag "Kill a word like `backward-kill-word'" emacs-word) - (const :tag "Kill a word like Bash would" unix-word) - (const :tag "Kill region even when inactive" nil)) + :type '(choice (const :tag "Kill region even when inactive" nil) + (const :tag "Kill a word like `backward-kill-word'" emacs-word) + (const :tag "Kill a word like Bash would" unix-word)) :group 'killing :version "31.1") @@ -5865,7 +5865,7 @@ Supply two arguments, character positions BEG and END indicating the ;; Pass mark first, then point, because the order matters when ;; calling `kill-append'. (interactive (progn - (let ((beg (mark)) + (let ((beg (mark kill-region-dwim)) (end (point))) (cond ((and kill-region-dwim (not (use-region-p))) @@ -5888,10 +5888,12 @@ Supply two arguments, character positions BEG and END indicating the ((filter-buffer-substring beg end 'delete))))) (when string ;STRING is nil if BEG = END ;; Add that string to the kill ring, one way or another. - (if (eq last-command 'kill-region) + (if (and (not (memq region '(unix-word emacs-word))) + (eq last-command 'kill-region)) (kill-append string (< end beg)) (kill-new string))) - (when (or string (eq last-command 'kill-region)) + (when (and (not (memq region '(unix-word emacs-word))) + (or string (eq last-command 'kill-region))) (setq this-command 'kill-region)) (setq deactivate-mark t) nil) commit 3924730200ccb79361ceac176e22731e862dbdd7 Author: Juri Linkov Date: Wed Sep 18 19:59:35 2024 +0300 ; Small fix for 'grep-change-to-grep-edit-mode' * lisp/progmodes/grep.el (grep-change-to-grep-edit-mode): Use 'substitute-command-keys' like in 'occur-edit-mode'. diff --git a/lisp/progmodes/grep.el b/lisp/progmodes/grep.el index 54006560224..b453ac60ed2 100644 --- a/lisp/progmodes/grep.el +++ b/lisp/progmodes/grep.el @@ -1122,7 +1122,8 @@ The only editable texts in a Grep-Edit buffer are the match results." (setq buffer-undo-list nil) (add-hook 'after-change-functions #'occur-after-change-function nil t) (run-mode-hooks 'grep-edit-mode-hook) - (message "Editing: \\[grep-edit-save-changes] to return to Grep mode")) + (message (substitute-command-keys + "Editing: Type \\[grep-edit-save-changes] to return to Grep mode"))) (defun grep-edit-save-changes () "Switch back to Grep mode." commit 5e377f4fcc0626065f930f68cff7a11f31c40ffe Author: Manuel Giraud Date: Fri Sep 6 09:47:33 2024 +0200 Make `dired-do-open' work on more *nix systems * lisp/dired-aux.el (dired-do-open): Make `dired-do-open' work on more *nix systems (bug#73004). diff --git a/lisp/dired-aux.el b/lisp/dired-aux.el index cd948bd7dd9..1d0e29b8782 100644 --- a/lisp/dired-aux.el +++ b/lisp/dired-aux.el @@ -1469,21 +1469,20 @@ system is determined by `shell-command-guess-open'." (when (and (memq system-type '(windows-nt)) (equal command "start")) (setq command "open")) - (when command - (dolist (file files) - (cond - ((memq system-type '(gnu/linux)) - (call-process command nil 0 nil file)) - ((memq system-type '(ms-dos)) - (shell-command (concat command " " (shell-quote-argument file)))) - ((memq system-type '(windows-nt)) - (w32-shell-execute command (convert-standard-filename file))) - ((memq system-type '(cygwin)) - (call-process command nil nil nil file)) - ((memq system-type '(darwin)) - (start-process (concat command " " file) nil command file)) - (t - (error "Open not supported on this system"))))))) + (if command + (dolist (file files) + (cond + ((memq system-type '(ms-dos)) + (shell-command (concat command " " (shell-quote-argument file)))) + ((memq system-type '(windows-nt)) + (w32-shell-execute command (convert-standard-filename file))) + ((memq system-type '(cygwin)) + (call-process command nil nil nil file)) + ((memq system-type '(darwin)) + (start-process (concat command " " file) nil command file)) + (t + (call-process command nil 0 nil file)))) + (error "Open not supported on this system")))) ;;; Commands that delete or redisplay part of the dired buffer commit 6d507d586a7ae2ab2caf32e32f2ae6134a90b1bd Author: Paul Eggert Date: Wed Sep 18 09:18:29 2024 -0700 yes-or-no-p now uses blankp rather than SYNTAX * src/fns.c: Do not include syntax.h; no longer needed. (Fyes_or_no_p): Use blankp rather than SYNTAX to check whether the prompt ends in nonspace. That way, the test doesn’t depend on the current buffer. diff --git a/src/fns.c b/src/fns.c index 370f7711b90..d3ee98c3bae 100644 --- a/src/fns.c +++ b/src/fns.c @@ -35,7 +35,6 @@ along with GNU Emacs. If not, see . */ #include "composite.h" #include "buffer.h" #include "intervals.h" -#include "syntax.h" #include "window.h" #include "puresize.h" #include "gnutls.h" @@ -3579,8 +3578,7 @@ by a mouse, or by some window-system gesture, or via a menu. */) ptrdiff_t promptlen = SCHARS (prompt); bool prompt_ends_in_nonspace = (0 < promptlen - && (SYNTAX (XFIXNAT (Faref (prompt, make_fixnum (promptlen - 1)))) - != Swhitespace)); + && !blankp (XFIXNAT (Faref (prompt, make_fixnum (promptlen - 1))))); AUTO_STRING (space_string, " "); prompt = CALLN (Fconcat, prompt, prompt_ends_in_nonspace ? space_string : empty_unibyte_string,