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

From: "Charles A. Roelli" <[email-masked]>
Date: Tue, 16 May 2017 21:08:07 +0200

I agree.  Not sure if the `read-library' function should go in a 
different file, but in any case it makes sense to let users take 
advantage of it in their code.

Attached is a revised patch with Philipp's other suggestions taken into 
account.

On 07/05/2017 17:07, Drew Adams wrote:
>> - Consider renaming `find-library-read' to
>>    `find-func--read-library' to make it internal.
>>    It's probably not intended as a public API.
> Why?  No.  Please do not consider that.  Not for a moment.
>
> FWIW, I completely disagree with this point of view and
> approach to Emacs Lisp.  Just the opposite.  Unless there is
> some _very_ important reason why something _must_ be branded
> as "internal", it should not be.
>
> It may be a hard habit to break, but the notion of a "public
> API" is generally inappropriate for Emacs Lisp.  Emacs users
> are also Emacs-Lisp developers. And yes, they do write their
> own libraries that read input.
>
> Just imagine, if an input-reading function such as
> `ffap-read-file-or-url', `read-file-name', `completing-read',
> `read-face-name', or `read-char' were declared at the outset
> to be "internal".  What's the point of such an artificial
> separation?
>
> In fact, I'd suggest that the library prefix be removed from
> `find-library-read' - just call it `read-library-name'.
> Elevate it; don't hide or suppress it.
>
> GNU Emacs in particular, and free software in general, have
> the explicit intention that users _are_ developers and that
> they look under the hood, tinker with engine parts, modify
> or make their own use of them, to create new and better
> things.
>
> And yes, Emacs development is driven not only by its
> maintainers or those most active in its C code or fixing
> its bugs.  It is driven also, and importantly, by users,
> who write their own code for their own uses, and who
> sometimes extend that code into 3rd-party libraries.
>
> Some such development even finds its way into distributed
> Emacs itself - either directly, by incorporating it, or
> indirectly, by copy or inspiration.  The latter happens
> more than most people, including Emacs maintainers, are
> aware of.
>
> Emacs would not be what it is today if it did not offer
> features written by its users (think Org).  And this has
> been true of Emacs since Day One - even before GNU Emacs.
>
> So let's please stop with the tendency to view Emacs
> development as an internal-vs-external thing: we core
> developers and the code we maintain vs you "lusers" and
> your customizations.
>
> If we are to have _any_ "internal" functions or variables
> then the burden should be to demonstrate strongly why
> a given one really _needs_ to be internal.  A priori,
> every single one should be "external" or, more exactly,
> "nil-ternal".
>
> I see no good reason why a general function that reads a
> library name should be flagged "internal".  Why should
> anyone be discouraged from using it in their code?  Why
> shouldn't everyone be encouraged to use it, if they want
> to read a library name?
>
> This kind of not-for-the-users attitude smacks of
> elitism, or at least seems control-freakish, even if it
> is unconscious.  Open the corral, please.  Emacs, and
> all of its code, belongs to its users.
>
> There is nothing special about this function.  It is
> useful generally.  And it should be called something
> like `read-library-name'.

>From 7edba19c49edeaa5efe244397dcd93f99fa6705d Mon Sep 17 00:00:00 2001
From: Charles A. Roelli <[email-masked]>
Date: Tue, 16 May 2017 20:40:50 +0200
Subject: [PATCH] New commands: find-library-other-window,
 find-library-other-frame

* lisp/emacs-lisp/find-func.el (find-library-other-window)
(find-library-other-frame): New commands to complement the existing
`find-library' command.
(read-library-name): New function to read a library name.
---
 etc/NEWS                     |    3 +
 lisp/emacs-lisp/find-func.el |   90 +++++++++++++++++++++++++-----------------
 2 files changed, 57 insertions(+), 36 deletions(-)

diff --git a/etc/NEWS b/etc/NEWS
index 25f0f18..bea4928 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -344,6 +344,9 @@ for DNS-querying functions 'nslookup-host', 'dns-lookup-host',
 and 'run-dig'.  Each function now accepts an optional name server
 argument interactively (with a prefix argument) and non-interactively.
 
+** Two new commands 'find-library-other-window' and
+'find-library-other-frame'.
+
 
 * Editing Changes in Emacs 26.1
 
diff --git a/lisp/emacs-lisp/find-func.el b/lisp/emacs-lisp/find-func.el
index d0acc14..43be71b 100644
--- a/lisp/emacs-lisp/find-func.el
+++ b/lisp/emacs-lisp/find-func.el
@@ -271,44 +271,61 @@ find-function-C-source
     (cons (current-buffer) (match-beginning 0))))
 
 ;;;###autoload
-(defun find-library (library &optional other-window)
-  "Find the Emacs Lisp source of LIBRARY.
-LIBRARY should be a string (the name of the library).  If the
-optional OTHER-WINDOW argument (i.e., the command argument) is
-specified, pop to a different window before displaying the
-buffer."
-  (interactive
-   (let* ((dirs (or find-function-source-path load-path))
-          (suffixes (find-library-suffixes))
-          (table (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))
-		 (thing-at-point 'symbol))))
-     (when (and def (not (test-completion def table)))
-       (setq def nil))
-     (list
-      (completing-read (if def
-                           (format "Library name (default %s): " def)
-			 "Library name: ")
-		       table nil nil nil nil def)
-      current-prefix-arg)))
+(defun find-library (library)
+  "Find the Emacs Lisp source of the LIBRARY near point.
+
+LIBRARY should be a string (the name of the library)."
+  (interactive (list (read-library-name)))
+  (prog1
+      (switch-to-buffer (find-file-noselect (find-library-name library)))
+    (run-hooks 'find-function-after-hook)))
+
+(defun read-library-name ()
+  "Read and return a library name, defaulting to the one near point."
+  (let* ((dirs (or find-function-source-path load-path))
+         (suffixes (find-library-suffixes))
+         (table (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))
+                (thing-at-point 'symbol))))
+    (when (and def (not (test-completion def table)))
+      (setq def nil))
+    (completing-read (if def
+                         (format "Library name (default %s): " def)
+                       "Library name: ")
+                     table nil nil nil nil def)))
+
+;;;###autoload
+(defun find-library-other-window (library)
+  "Find, in another window, the file defining LIBRARY at or near point.
+
+See `find-library' for more details."
+  (interactive (list (read-library-name)))
+  (prog1
+      (switch-to-buffer-other-window (find-file-noselect
+                                      (find-library-name library)))
+    (run-hooks 'find-function-after-hook)))
+
+;;;###autoload
+(defun find-library-other-frame (library)
+  "Find, in another frame, the file defining LIBRARY at or near point.
+
+See `find-library' for more details."
+  (interactive (list (read-library-name)))
   (prog1
-      (funcall (if other-window
-                   'pop-to-buffer
-                 'pop-to-buffer-same-window)
-               (find-file-noselect (find-library-name library)))
+      (switch-to-buffer-other-frame (find-file-noselect
+                                     (find-library-name library)))
     (run-hooks 'find-function-after-hook)))
 
 ;;;###autoload
-- 
1.7.4.4