Commit f925fc93 authored by Stefan Monnier's avatar Stefan Monnier
Browse files

Add `predicate' arg to `read-buffer' and use it for erc-iswitchb

Fixes: debbugs:20116

* src/minibuf.c (Fread_buffer): Add `predicate' argument.
* src/callint.c (Fcall_interactively): Adjust calls accordingly.

* lisp/erc/erc.el (erc-switch-to-buffer): Rename from erc-iswitchb and rewrite
using read-buffer.
(erc--buffer-p): New function, extracted from erc-buffer-filter.
(erc-buffer-filter): Use it.
(erc-with-all-buffers-of-server): Silence compile warning if the return
value is unused.
(erc-is-valid-nick-p, erc-common-server-suffixes, erc-get-arglist)
(erc-command-name, erc-popup-input-buffer): Use \` and \' to match
beg/end of string.

* lisp/obsolete/iswitchb.el (iswitchb-read-buffer): Add `predicate' arg.
* lisp/isearchb.el (isearchb-iswitchb): Adjust accordingly.
* lisp/ido.el (ido-read-buffer): Add `predicate' argument.
* lisp/misearch.el (unload-function-defs-list): Declare before use.
parent 43a847c0
......@@ -594,6 +594,8 @@ a typographically-correct documents.
* Incompatible Lisp Changes in Emacs 25.1
** read-buffer-function can now be called with a 4th argument (`predicate').
** completion-table-dynamic stays in the minibuffer.
If you want the old behavior of calling the function in the buffer
from which the minibuffer was entered, call it with the new argument
......@@ -631,6 +633,8 @@ word syntax, use `\sw' instead.
* Lisp Changes in Emacs 25.1
** `read-buffer' takes a new `predicate' argument.
** Emacs Lisp now supports generators.
** New finalizer facility for running code when objects
2015-03-16 Stefan Monnier <>
* obsolete/iswitchb.el (iswitchb-read-buffer): Add `predicate' arg.
* isearchb.el (isearchb-iswitchb): Adjust accordingly.
* ido.el (ido-read-buffer): Add `predicate' argument.
* misearch.el (unload-function-defs-list): Declare before use.
2015-03-16 Vibhav Pant <>
* net/browse-url.el (browse-url-browser-function): Add "Conkeror".
......@@ -463,7 +463,7 @@ color displays. By default, the delimiters are used only on TTYs."
:type 'boolean
:group 'viper)
(defcustom viper-read-buffer-function 'read-buffer
(defcustom viper-read-buffer-function #'read-buffer
"Function to use for prompting the user for a buffer name."
:type 'symbol
:group 'viper)
2015-03-16 Stefan Monnier <>
* erc.el (erc-switch-to-buffer): Rename from erc-iswitchb and rewrite
using read-buffer (bug#20116).
(erc--buffer-p): New function, extracted from erc-buffer-filter.
(erc-buffer-filter): Use it.
(erc-with-all-buffers-of-server): Silence compile warning if the return
value is unused.
(erc-is-valid-nick-p, erc-common-server-suffixes, erc-get-arglist)
(erc-command-name, erc-popup-input-buffer): Use \` and \' to match
beg/end of string.
2015-03-03 Kelvin White <>
* erc.el: Add old version string back to file header for
......@@ -1110,7 +1110,7 @@ which the local user typed."
(define-key map "\C-a" 'erc-bol)
(define-key map [home] 'erc-bol)
(define-key map "\C-c\C-a" 'erc-bol)
(define-key map "\C-c\C-b" 'erc-iswitchb)
(define-key map "\C-c\C-b" 'erc-switch-to-buffer)
(define-key map "\C-c\C-c" 'erc-toggle-interpret-controls)
(define-key map "\C-c\C-d" 'erc-input-action)
(define-key map "\C-c\C-e" 'erc-toggle-ctcp-autoresponse)
......@@ -1647,6 +1647,14 @@ If PROC is not supplied, all processes are searched."
(throw 'buffer (current-buffer)))))
(defun erc--buffer-p (buf predicate proc)
(with-current-buffer buf
(and (derived-mode-p 'erc-mode)
(or (not proc)
(eq proc erc-server-process))
(funcall predicate)
(defun erc-buffer-filter (predicate &optional proc)
"Return a list of `erc-mode' buffers matching certain criteria.
PREDICATE is a function executed with each buffer, if it returns t, that buffer
......@@ -1659,12 +1667,7 @@ server connection, or nil which means all open connections."
(mapcar (lambda (buf)
(when (buffer-live-p buf)
(with-current-buffer buf
(and (eq major-mode 'erc-mode)
(or (not proc)
(eq proc erc-server-process))
(funcall predicate)
(erc--buffer-p buf predicate proc)))
(defun erc-buffer-list (&optional predicate proc)
......@@ -1695,42 +1698,32 @@ nil."
;; Silence the byte-compiler by binding the result of mapcar to
;; a variable.
(ignore res)
;; (iswitchb-mode) will autoload iswitchb.el
(defvar iswitchb-temp-buflist)
(declare-function iswitchb-read-buffer "iswitchb"
(prompt &optional default require-match start matches-set))
(defvar iswitchb-make-buflist-hook)
(defun erc-iswitchb (&optional arg)
"Use `iswitchb-read-buffer' to prompt for a ERC buffer to switch to.
(define-obsolete-function-alias 'erc-iswitchb 'erc-switch-to-buffer "25.1")
(defun erc-switch-to-buffer (&optional arg)
"Prompt for a ERC buffer to switch to.
When invoked with prefix argument, use all erc buffers. Without prefix
ARG, allow only buffers related to same session server.
If `erc-track-mode' is in enabled, put the last element of
`erc-modified-channels-alist' in front of the buffer list.
Due to some yet unresolved reason, global function `iswitchb-mode'
needs to be active for this function to work."
`erc-modified-channels-alist' in front of the buffer list."
(interactive "P")
(let ((enabled (bound-and-true-p iswitchb-mode)))
(or enabled (iswitchb-mode 1))
(let ((iswitchb-make-buflist-hook
(lambda ()
(setq iswitchb-temp-buflist
(mapcar 'buffer-name
(when arg erc-server-process)))))))
"Switch-to: "
(if (boundp 'erc-modified-channels-alist)
(buffer-name (caar (last erc-modified-channels-alist)))
(or enabled (iswitchb-mode -1)))))
(read-buffer "Switch to ERC buffer: "
(when (boundp 'erc-modified-channels-alist)
(buffer-name (caar (last erc-modified-channels-alist))))
;; Only allow ERC buffers in the same session.
(let ((proc (unless arg erc-server-process)))
(lambda (bufname)
(let ((buf (get-buffer bufname)))
(when buf
(erc--buffer-p buf (lambda () t) proc)
(with-current-buffer buf
(and (derived-mode-p 'erc-mode)
(or (null proc)
(eq proc erc-server-process)))))))))))
(defun erc-channel-list (proc)
"Return a list of channel buffers.
......@@ -2189,7 +2182,7 @@ be invoked for the values of the other parameters."
Arguments are the same as for `erc'."
(interactive (erc-select-read-args))
(let ((erc-server-connect-function 'erc-open-tls-stream))
(apply 'erc r)))
(apply #'erc r)))
(defun erc-open-tls-stream (name buffer host port)
"Open an TLS stream to an IRC server.
......@@ -2403,7 +2396,7 @@ If STRING is nil, the function does nothing."
(defun erc-is-valid-nick-p (nick)
"Check if NICK is a valid IRC nickname."
(string-match (concat "^" erc-valid-nick-regexp "$") nick))
(string-match (concat "\\`" erc-valid-nick-regexp "\\'") nick))
(defun erc-display-line (string &optional buffer)
"Display STRING in the ERC BUFFER.
......@@ -2602,9 +2595,9 @@ server within `erc-lurker-threshold-time'. See also
(defcustom erc-common-server-suffixes
'(("$" . "OPN")
("$" . "freenode")
("$" . "OFTC"))
'(("\\'" . "OPN")
("\\'" . "freenode")
("\\'" . "OFTC"))
"Alist of common server name suffixes.
This variable is used in mode-line display to save screen
real estate. Set it to nil if you want to avoid changing
......@@ -2640,7 +2633,7 @@ ARGS, PARSED, and TYPE are used to format MSG sensibly.
See also `erc-format-message' and `erc-display-line'."
(let ((string (if (symbolp msg)
(apply 'erc-format-message msg args)
(apply #'erc-format-message msg args)
(setq string
......@@ -2689,7 +2682,7 @@ See also `erc-server-send'."
(defun erc-get-arglist (fun)
"Return the argument list of a function without the parens."
(let ((arglist (format "%S" (erc-function-arglist fun))))
(if (string-match "^(\\(.*\\))$" arglist)
(if (string-match "\\`(\\(.*\\))\\'" arglist)
(match-string 1 arglist)
......@@ -2705,7 +2698,7 @@ is not alive, nil otherwise."
"For CMD being the function name of a ERC command, something like
erc-cmd-FOO, this returns a string /FOO."
(let ((command-name (symbol-name cmd)))
(if (string-match "^erc-cmd-\\(.*\\)$" command-name)
(if (string-match "\\`erc-cmd-\\(.*\\)\\'" command-name)
(concat "/" (match-string 1 command-name))
......@@ -2796,7 +2789,7 @@ VALUE is computed by evaluating the rest of LINE in Lisp."
(concat "Available user variables:\n"
(lambda (var)
(let ((val (symbol-value var)))
......@@ -3775,7 +3768,7 @@ Unban all currently banned users in the current channel."
(erc-server-send (format "MODE %s b" chnl)))))
(t (let ((bans (mapcar 'cdr erc-channel-banlist)))
(t (let ((bans (mapcar #'cdr erc-channel-banlist)))
(when bans
;; Glob the bans into groups of three, and carry out the unban.
;; eg. /mode #foo -bbb a*!*@* b*!*@* c*!*@*
......@@ -3930,7 +3923,7 @@ If `point' is at the beginning of a channel name, use that as default."
(concat "Set topic of " (erc-default-target) ": ")
(when erc-channel-topic
(let ((ss (split-string erc-channel-topic "\C-o")))
(cons (apply 'concat (if (cdr ss) (butlast ss) ss))
(cons (apply #'concat (if (cdr ss) (butlast ss) ss))
(let ((topic-list (split-string topic "\C-o"))) ; strip off the topic setter
(erc-cmd-TOPIC (concat (erc-default-target) " " (car topic-list)))))
......@@ -5052,7 +5045,7 @@ arg-modes is a list of triples of the form:
(if (string-match "^\\s-*\\(\\S-+\\)\\(\\s-.*$\\|$\\)" mode-string)
(let ((chars (mapcar 'char-to-string (match-string 1 mode-string)))
(let ((chars (mapcar #'char-to-string (match-string 1 mode-string)))
;; arguments in channel modes
(args-str (match-string 2 mode-string))
(args nil)
......@@ -5998,7 +5991,7 @@ Returns a list of the form (HIGH LOW), compatible with Emacs time format."
(if (> minutes 0)
`("%d minutes, %d seconds" ,minutes ,seconds)
`("%d seconds" ,seconds))))
output (apply 'format format-args))
output (apply #'format format-args))
;; Change all "1 units" to "1 unit".
(while (string-match "\\([^0-9]\\|^\\)1 \\S-+\\(s\\)" output)
(setq output (erc-replace-match-subexpression-in-string
......@@ -6246,7 +6239,7 @@ if `erc-away' is non-nil."
(defun erc-format-channel-modes ()
"Return the current channel's modes."
(concat (apply 'concat
(concat (apply #'concat
"+" erc-channel-modes)
(cond ((and erc-channel-user-limit erc-channel-key)
(if erc-show-channel-key-p
......@@ -6438,7 +6431,7 @@ All windows are opened in the current frame."
"Mode: "
(mapcar (lambda (e)
(list (symbol-name e)))
(apropos-internal "-mode$" 'commandp))
(apropos-internal "-mode\\'" 'commandp))
nil t))))
(pop-to-buffer (make-indirect-buffer (current-buffer) buffer-name))
(funcall mode)
......@@ -6634,7 +6627,7 @@ See also `format-spec'."
(error "No format spec for message %s" msg))
(when (functionp entry)
(setq entry (apply entry args)))
(format-spec entry (apply 'format-spec-make args))))
(format-spec entry (apply #'format-spec-make args))))
;;; Various hook functions
......@@ -1590,10 +1590,10 @@ enable the mode if ARG is omitted or nil."
(when ido-everywhere
(when (memq ido-mode '(both file))
(put 'ido-everywhere 'file (cons read-file-name-function nil))
(setq read-file-name-function 'ido-read-file-name))
(setq read-file-name-function #'ido-read-file-name))
(when (memq ido-mode '(both buffer))
(put 'ido-everywhere 'buffer (cons read-buffer-function nil))
(setq read-buffer-function 'ido-read-buffer))))
(setq read-buffer-function #'ido-read-buffer))))
(defvar ido-minor-mode-map-entry nil)
......@@ -4782,7 +4782,7 @@ Modified from `icomplete-completions'."
(put 'dired-do-rename 'ido 'ignore)
(defun ido-read-buffer (prompt &optional default require-match)
(defun ido-read-buffer (prompt &optional default require-match predicate)
"Ido replacement for the built-in `read-buffer'.
Return the name of a buffer selected.
PROMPT is the prompt to give to the user. DEFAULT if given is the default
......@@ -4796,7 +4796,7 @@ If REQUIRE-MATCH is non-nil, an existing buffer must be selected."
(if (eq ido-exit 'fallback)
(let ((read-buffer-function nil))
(run-hook-with-args 'ido-before-fallback-functions 'read-buffer)
(read-buffer prompt default require-match))
(read-buffer prompt default require-match predicate))
......@@ -75,7 +75,9 @@
;; killing iswitchb.el and then trying to switch back is broken
;; make sure TAB isn't broken
(require 'iswitchb)
;;; Code:
(require 'iswitchb) ;FIXME: Don't rely on iswitchb!
(defgroup isearchb nil
"Switch between buffers using a mechanism like isearch."
......@@ -118,7 +120,7 @@ Its purpose is to pass different call arguments to
(let* ((prompt "iswitch ")
(iswitchb-method 'samewindow)
(buf (iswitchb-read-buffer prompt nil nil iswitchb-text t)))
(buf (iswitchb-read-buffer prompt nil nil nil iswitchb-text t)))
(if (eq iswitchb-exit 'findfile)
(call-interactively 'find-file)
(when buf
......@@ -234,7 +234,7 @@ set in `multi-isearch-buffers' or `multi-isearch-buffers-regexp'."
(ido-ignore-item-temp-list bufs))
(while (not (string-equal
(setq buf (read-buffer
(if (eq read-buffer-function 'ido-read-buffer)
(if (eq read-buffer-function #'ido-read-buffer)
"Next buffer to search (C-j to end): "
"Next buffer to search (RET to end): ")
nil t))
......@@ -377,6 +377,8 @@ whose file names match the specified wildcard."
(goto-char (if isearch-forward (point-min) (point-max)))
(isearch-forward-regexp nil t)))
(defvar unload-function-defs-list)
(defun multi-isearch-unload-function ()
"Remove autoloaded variables from `unload-function-defs-list'.
Also prevent the feature from being reloaded via `isearch-mode-hook'."
......@@ -175,10 +175,10 @@
;; iswitchb-read-buffer has been written to be a drop in replacement
;; for the normal buffer selection routine `read-buffer'. To use
;; iswitch for all buffer selections in Emacs, add:
;; (setq read-buffer-function 'iswitchb-read-buffer)
;; (setq read-buffer-function #'iswitchb-read-buffer)
;; (This variable was introduced in Emacs 20.3.)
;; XEmacs users can get the same behavior by doing:
;; (defalias 'read-buffer 'iswitchb-read-buffer)
;; (defalias 'read-buffer #'iswitchb-read-buffer)
;; since `read-buffer' is defined in lisp.
;; Using iswitchb for other completion tasks.
......@@ -586,7 +586,7 @@ in a separate window.
(defun iswitchb-read-buffer (prompt &optional default require-match
start matches-set)
_predicate start matches-set)
"Replacement for the built-in `read-buffer'.
Return the name of a buffer selected.
PROMPT is the prompt to give to the user.
......@@ -1369,7 +1369,7 @@ See also `multi-occur-in-matching-buffers'."
(ido-ignore-item-temp-list bufs))
(while (not (string-equal
(setq buf (read-buffer
(if (eq read-buffer-function 'ido-read-buffer)
(if (eq read-buffer-function #'ido-read-buffer)
"Next buffer to search (C-j to end): "
"Next buffer to search (RET to end): ")
nil t))
2015-03-16 Stefan Monnier <>
* minibuf.c (Fread_buffer): Add `predicate' argument.
* callint.c (Fcall_interactively): Adjust calls accordingly.
2015-03-15 Eli Zaretskii <>
* xdisp.c (handle_invisible_prop): Fix up it->position even when
......@@ -531,13 +531,13 @@ invoke it. If KEYS is omitted or nil, the return value of
args[i] = Fcurrent_buffer ();
if (EQ (selected_window, minibuf_window))
args[i] = Fother_buffer (args[i], Qnil, Qnil);
args[i] = Fread_buffer (callint_message, args[i], Qt);
args[i] = Fread_buffer (callint_message, args[i], Qt, Qnil);
case 'B': /* Name of buffer, possibly nonexistent. */
args[i] = Fread_buffer (callint_message,
Fother_buffer (Fcurrent_buffer (), Qnil, Qnil),
Qnil, Qnil);
case 'c': /* Character. */
......@@ -1081,7 +1081,7 @@ A user option, or customizable variable, is one for which
return Fintern (name, Qnil);
DEFUN ("read-buffer", Fread_buffer, Sread_buffer, 1, 3, 0,
DEFUN ("read-buffer", Fread_buffer, Sread_buffer, 1, 4, 0,
doc: /* Read the name of a buffer and return as a string.
Prompt with PROMPT.
Optional second arg DEF is value to return if user enters an empty line.
......@@ -1093,8 +1093,11 @@ The argument PROMPT should be a string ending with a colon and a space.
If `read-buffer-completion-ignore-case' is non-nil, completion ignores
case while reading the buffer name.
If `read-buffer-function' is non-nil, this works by calling it as a
function, instead of the usual behavior. */)
(Lisp_Object prompt, Lisp_Object def, Lisp_Object require_match)
function, instead of the usual behavior.
Optional arg PREDICATE if non-nil is a function limiting the buffers that can
be considered. */)
(Lisp_Object prompt, Lisp_Object def, Lisp_Object require_match,
Lisp_Object predicate)
Lisp_Object result;
char *s;
......@@ -1136,11 +1139,16 @@ function, instead of the usual behavior. */)
result = Fcompleting_read (prompt, intern ("internal-complete-buffer"),
Qnil, require_match, Qnil,
predicate, require_match, Qnil,
Qbuffer_name_history, def, Qnil);
result = call3 (Vread_buffer_function, prompt, def, require_match);
result = (NILP (predicate)
/* Partial backward compatibility for older read_buffer_functions
which don't expect a `predicate' argument. */
? call3 (Vread_buffer_function, prompt, def, require_match)
: call4 (Vread_buffer_function, prompt, def, require_match,
return unbind_to (count, result);
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment