Subject: bug#26712: other-window/frame versions of find-library

From: "Charles A. Roelli" <[email-masked]>
Date: Sun, 11 Jun 2017 12:44:56 +0200

Please see the attached two patches.  The first implements
'find-function-or-library' (what I sent previously).  The second patch
makes the 'find-function-setup-keys' bindings by default, and they're
documented in the manual.

On 04/06/2017 04:54, Richard Stallman wrote:
> [[[ To any NSA and FBI agents reading my email: please consider    ]]]
> [[[ whether defending the US Constitution against all enemies,     ]]]
> [[[ foreign or domestic, requires you to follow Snowden's example. ]]]
>
>    > It seems "(emacs) Misc Help" could be ok.
>
> I agree.
>

>From f21249122162835e1d22ca72fec6212944328859 Mon Sep 17 00:00:00 2001
From: Charles A. Roelli <[email-masked]>
Date: Mon, 29 May 2017 21:35:24 +0200
Subject: [PATCH 1/2] New commands: find-function-or-library
 (-other-window/-frame)

* lisp/emacs-lisp/find-func.el (read-function-or-library-name):
New function for reading a function or library name.
(find-function-or-library, find-function-or-library-other-window)
(find-function-or-library-other-frame): New commands.
(find-function-setup-keys): Replace 'find-function' bindings with
bindings to 'find-function-or-library'.
* etc/NEWS: Mention 'find-function-or-library' and new bindings
made by 'find-function-setup-keys'.
---
 etc/NEWS                     |    7 +++-
 lisp/emacs-lisp/find-func.el |   90 ++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 93 insertions(+), 4 deletions(-)

diff --git a/etc/NEWS b/etc/NEWS
index 7972511..6ed668c 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -364,13 +364,18 @@ large integers from being displayed as characters.
 ** Two new commands for finding the source code of Emacs Lisp
 libraries: 'find-library-other-window' and 'find-library-other-frame'.
 
-+++
 ** The new variable 'display-raw-bytes-as-hex' allows to change the
 display of raw bytes from octal to hex.
 
 ** You can now provide explicit field numbers in format specifiers.
 For example, '(format "%2$s %1$s" "X" "Y")' produces "Y X".
 
+** 'find-function-setup-keys' now binds 'C-x F', 'C-x 4 F' and 'C-x 5
+F' to the new command 'find-function-or-library' and its
+other-window/-frame counterparts.  The new commands find the Emacs
+Lisp source code of a function or library, defaulting to the function
+or library closest to point.
+
 
 * Editing Changes in Emacs 26.1
 
diff --git a/lisp/emacs-lisp/find-func.el b/lisp/emacs-lisp/find-func.el
index 9b98f05..9943598 100644
--- a/lisp/emacs-lisp/find-func.el
+++ b/lisp/emacs-lisp/find-func.el
@@ -310,6 +310,40 @@ read-library-name
                        "Library name: ")
                      table nil nil nil nil def)))
 
+(defun read-function-or-library-name ()
+  "Read and return a function or library name, defaulting to the one near point.
+
+A function name is the name of a symbol that satisfies the
+predicate `fboundp'.  A library name is the filename of an Emacs
+Lisp library located in a directory under `load-path' (or
+`find-function-source-path', if non-nil)."
+  (let* ((dirs (or find-function-source-path load-path))
+         (suffixes (find-library-suffixes))
+         (table (completion-table-merge
+                 (apply-partially 'completion-table-with-predicate
+                                  obarray 'fboundp t)
+                 (apply-partially 'locate-file-completion-table
+                                  dirs suffixes)))
+         (def (if (eq (function-called-at-point) 'require)
+                  ;; `function-called-at-point' may return 'require
+                  ;; with `point' anywhere on this line.  So wrap the
+                  ;; `save-excursion' below in a `condition-case' to
+                  ;; avoid reporting a scan-error here.
+                  (condition-case nil
+                      (save-excursion
+                        (backward-up-list)
+                        (forward-char)
+                        (forward-sexp 2)
+                        (thing-at-point 'symbol))
+                    (error nil))
+                (symbol-name (function-called-at-point)))))
+    (when (and def (not (test-completion def table)))
+      (setq def nil))
+    (completing-read (if def
+                         (format "Function or library name (default %s): " def)
+                       "Function or library name: ")
+                     table nil nil nil nil def)))
+
 ;;;###autoload
 (defun find-library-other-window (library)
   "Find the Emacs Lisp source of LIBRARY in another window.
@@ -537,6 +571,56 @@ find-function-other-frame
   (find-function-do-it function nil 'switch-to-buffer-other-frame))
 
 ;;;###autoload
+(defun find-function-or-library (function-or-library)
+  "Find the definition of the FUNCTION-OR-LIBRARY near point.
+
+Finds the source file containing the definition of the
+function (selected by `function-called-at-point') or
+library (loaded with `require') near point in a buffer and places
+point before the definition.
+
+FUNCTION-OR-LIBRARY is searched for in
+`find-function-source-path', if non-nil, otherwise in
+`load-path'.  See also `find-function-recenter-line' and
+`find-function-after-hook'.
+
+If FUNCTION-OR-LIBRARY names both a function and a library, finds
+the corresponding function definition."
+  (interactive (list (read-function-or-library-name)))
+  (let ((sym (if (stringp function-or-library)
+                 (intern function-or-library)
+               function-or-library)))
+    (if (fboundp sym)
+        (find-function-do-it sym nil 'switch-to-buffer)
+      (find-library function-or-library))))
+
+;;;###autoload
+(defun find-function-or-library-other-window (function-or-library)
+  "Find, in another window, the definition of FUNCTION-OR-LIBRARY near point.
+
+See `find-function' for more details."
+  (interactive (list (read-function-or-library-name)))
+  (let ((sym (if (stringp function-or-library)
+                 (intern function-or-library)
+               function-or-library)))
+    (if (fboundp sym)
+        (find-function-do-it sym nil 'switch-to-buffer-other-window)
+      (find-library-other-window function-or-library))))
+
+;;;###autoload
+(defun find-function-or-library-other-frame (function-or-library)
+  "Find, in another frame, the definition of FUNCTION-OR-LIBRARY near point.
+
+See `find-function' for more details."
+  (interactive (list (read-function-or-library-name)))
+  (let ((sym (if (stringp function-or-library)
+                 (intern function-or-library)
+               function-or-library)))
+    (if (fboundp sym)
+        (find-function-do-it sym nil 'switch-to-buffer-other-frame)
+      (find-library-other-frame function-or-library))))
+
+;;;###autoload
 (defun find-variable-noselect (variable &optional file)
   "Return a pair `(BUFFER . POINT)' pointing to the definition of VARIABLE.
 
@@ -691,9 +775,9 @@ find-variable-at-point
 ;;;###autoload
 (defun find-function-setup-keys ()
   "Define some key bindings for the find-function family of functions."
-  (define-key ctl-x-map "F" 'find-function)
-  (define-key ctl-x-4-map "F" 'find-function-other-window)
-  (define-key ctl-x-5-map "F" 'find-function-other-frame)
+  (define-key ctl-x-map "F" 'find-function-or-library)
+  (define-key ctl-x-4-map "F" 'find-function-or-library-other-window)
+  (define-key ctl-x-5-map "F" 'find-function-or-library-other-frame)
   (define-key ctl-x-map "K" 'find-function-on-key)
   (define-key ctl-x-4-map "K" 'find-function-on-key-other-window)
   (define-key ctl-x-5-map "K" 'find-function-on-key-other-frame)
-- 
1.7.4.4

>From ec6d7c242f7d19bfcaa760e9a991e83244f44974 Mon Sep 17 00:00:00 2001
From: Charles A. Roelli <[email-masked]>
Date: Sun, 4 Jun 2017 11:56:58 +0200
Subject: [PATCH 2/2] Make 'find-function-setup-keys' bindings default

* etc/NEWS: Mention the default bindings that were formerly made by
'find-function-setup-keys'.  Remove a previous entry that has been
superceded by the recent addition of 'find-library-other-window'.
* doc/emacs/help.texi (Misc Help): Document the new bindings.
* lisp/bindings.el: Add bindings formerly made by
'find-function-setup-keys': 'C-x F', 'C-x K', 'C-x V' and
'C-x 4'/'C-x 5' variants.
* lisp/find-func.el (find-function-setup-keys): Alias to #'ignore,
and make it obsolete.
---
 doc/emacs/help.texi          |   49 ++++++++++++++++++++++++++++++++++++++++++
 etc/NEWS                     |   17 ++++++-------
 lisp/bindings.el             |   11 +++++++++
 lisp/emacs-lisp/find-func.el |   14 ++---------
 4 files changed, 71 insertions(+), 20 deletions(-)

diff --git a/doc/emacs/help.texi b/doc/emacs/help.texi
index 548ca6a..74a06f5 100644
--- a/doc/emacs/help.texi
+++ b/doc/emacs/help.texi
@@ -588,6 +588,55 @@ Misc Help
 which marks a defun.  However, @kbd{@key{ESC} @key{F1}} and
 @kbd{@key{ESC} ?} work fine.)
 
+@kindex C-x F
+@findex find-function-or-library
+@kindex C-x 4 F
+@findex find-function-or-library-other-window
+@kindex C-x 5 F
+@findex find-function-or-library-other-frame
+@kindex C-x K
+@findex find-function-on-key
+@kindex C-x 4 K
+@findex find-function-on-key-other-window
+@kindex C-x 5 K
+@findex find-function-on-key-other-frame
+@kindex C-x V
+@findex find-variable
+@kindex C-x 4 V
+@findex find-variable-other-window
+@kindex C-x 5 V
+@findex find-variable-other-frame
+  When reading or writing Emacs Lisp code, it is often helpful to
+visit the source of other Emacs Lisp functions, libraries and
+variables.  The following commands are helpful for doing that:
+
+@table @kbd
+@item C-x F
+Find a function or library, with the function or library closest to
+point as a suggestion (@code{find-function-or-library}).
+@item C-x 4 F
+Idem., in another window
+(@code{find-function-or-library-other-window}).
+@item C-x 5 F
+Idem., in another frame (@code{find-function-or-library-other-frame}).
+@item C-x K
+Find a function on a given key, which you type interactively
+(@code{find-function-on-key}).
+@item C-x 4 K
+Idem., in another window
+(@code{find-function-on-key-other-window}).
+@item C-x 5 K
+Idem., in another frame (@code{find-function-on-key-other-frame}).
+@item C-x V
+Find a variable, with the variable closest to point as a suggestion
+(@code{find-variable}).
+@item C-x 4 V
+Idem., in another window
+(@code{find-variable-other-window}).
+@item C-x 5 V
+Idem., in another frame (@code{find-variable-other-frame}).
+@end table
+
 @node Help Files
 @section Help Files
 
diff --git a/etc/NEWS b/etc/NEWS
index 6ed668c..2b31cc0 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -211,10 +211,6 @@ face instead of the 'escape-glyph' face.
 part of minibuffers.
 
 ---
-** 'find-library' now takes a prefix argument to pop to a different
-window.
-
----
 ** 'process-attributes' on Darwin systems now returns more information.
 
 +++
@@ -370,11 +366,14 @@ display of raw bytes from octal to hex.
 ** You can now provide explicit field numbers in format specifiers.
 For example, '(format "%2$s %1$s" "X" "Y")' produces "Y X".
 
-** 'find-function-setup-keys' now binds 'C-x F', 'C-x 4 F' and 'C-x 5
-F' to the new command 'find-function-or-library' and its
-other-window/-frame counterparts.  The new commands find the Emacs
-Lisp source code of a function or library, defaulting to the function
-or library closest to point.
+** 'C-x F', 'C-x 4 F' and 'C-x 5 F' are bound to the new command
+'find-function-or-library' and its other-window/-frame counterparts.
+The new commands find the Emacs Lisp source code of a function or
+library, defaulting to the function or library closest to point.  'C-x
+K' and 'C-x V' are bound to 'find-function-on-key' and
+'find-variable', with equivalent other-window/-frame commands in the
+'C-x 4' and 'C-x 5' keymaps.  These were formerly bound by the
+function 'find-function-setup-keys', which is now obsolete.
 
 
 * Editing Changes in Emacs 26.1
diff --git a/lisp/bindings.el b/lisp/bindings.el
index 0994b71..4807b57 100644
--- a/lisp/bindings.el
+++ b/lisp/bindings.el
@@ -1325,6 +1325,17 @@ esc-map
 (define-key ctl-x-4-map "a" 'add-change-log-entry-other-window)
 (define-key ctl-x-4-map "c" 'clone-indirect-buffer-other-window)
 
+;; from emacs-lisp/find-func.el
+(define-key ctl-x-map "F" 'find-function-or-library)
+(define-key ctl-x-4-map "F" 'find-function-or-library-other-window)
+(define-key ctl-x-5-map "F" 'find-function-or-library-other-frame)
+(define-key ctl-x-map "K" 'find-function-on-key)
+(define-key ctl-x-4-map "K" 'find-function-on-key-other-window)
+(define-key ctl-x-5-map "K" 'find-function-on-key-other-frame)
+(define-key ctl-x-map "V" 'find-variable)
+(define-key ctl-x-4-map "V" 'find-variable-other-window)
+(define-key ctl-x-5-map "V" 'find-variable-other-frame)
+
 ;; Signal handlers
 (define-key special-event-map [sigusr1] 'ignore)
 (define-key special-event-map [sigusr2] 'ignore)
diff --git a/lisp/emacs-lisp/find-func.el b/lisp/emacs-lisp/find-func.el
index 9943598..c08df49 100644
--- a/lisp/emacs-lisp/find-func.el
+++ b/lisp/emacs-lisp/find-func.el
@@ -773,17 +773,9 @@ find-variable-at-point
       (find-variable-other-window symb))))
 
 ;;;###autoload
-(defun find-function-setup-keys ()
-  "Define some key bindings for the find-function family of functions."
-  (define-key ctl-x-map "F" 'find-function-or-library)
-  (define-key ctl-x-4-map "F" 'find-function-or-library-other-window)
-  (define-key ctl-x-5-map "F" 'find-function-or-library-other-frame)
-  (define-key ctl-x-map "K" 'find-function-on-key)
-  (define-key ctl-x-4-map "K" 'find-function-on-key-other-window)
-  (define-key ctl-x-5-map "K" 'find-function-on-key-other-frame)
-  (define-key ctl-x-map "V" 'find-variable)
-  (define-key ctl-x-4-map "V" 'find-variable-other-window)
-  (define-key ctl-x-5-map "V" 'find-variable-other-frame))
+(defalias 'find-function-setup-keys 'ignore)
+(make-obsolete 'find-function-setup-keys
+  "commands from `find-func' are bound by default." "26.1")
 
 (provide 'find-func)
 
-- 
1.7.4.4