emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: locate-library, the NOSUFFIX arg and a [PATCH]


From: MON KEY
Subject: Re: locate-library, the NOSUFFIX arg and a [PATCH]
Date: Thu, 21 Jan 2010 18:58:15 -0500

Hi Stefan,

On Thu, Jan 21, 2010 at 9:08 AM, Stefan Monnier
<address@hidden> wrote:
>> ,----
>> | It can omit the suffix (a.k.a. file-name extension) if NOSUFFIX is
>> | nil (which is the default, see below).
>> `----
>
> This is poorly worded but means that it will not only look for files
> of the form DIR/FILE.SUFFIX but also for DIR/FILE (i.e. it will add the
> empty string as a valid suffix).
>

A library is not a file. It is an abstraction of one. This is a subtle but
important difference as you are no doubt well aware.

The current docstring begins:

,----
| Show the precise file name of Emacs library library.
`----

There can not be a precise file name for an abstraction...

(get-load-suffixes)
=> (".elc" ".elc.gz" ".el" ".el.gz") ;and sometimes ""

Unless there is a most bona fide of the library suffixe.
Or, some pigs are more equal than others.

> This is poorly worded but means that it will not only look for files
> of the form DIR/FILE.SUFFIX but also for DIR/FILE (i.e. it will add the
> empty string as a valid suffix).

A) It doesn't do that now.

B) If the empty string is a valid suffix then all strings are potentially valid
   library suffixes.

With regards A my patch and the newly modified version below address this.

With regards B, is this your intention here?. If so, I don't believe this a case
of poor wording. It is a situation where the user visible ``spec'' (i.e. the
docstring) says one thing but the function does something entirely different
(badly) b/c the empty string becomes the operative factor _not_ the value of
`load-suffixes'.

Regardless, you've ignored the second portion of the docs which negates _your_
interpretation above, and have neglected to explain or address my initial query:

 "Aren't these two statements mutually exclusive?"

,----
| Optional second arg NOSUFFIX non-nil means don't add suffixes `load-suffixes'
| to the specified name LIBRARY.
`----

According to the docs we have:

o If NOSUFFIX is nil - omit the suffix
o If NOSUFIX is non-nil don't add suffixes `load-suffixes'.

What other suffixes are there other than `load-suffixes'?

The docs don't explicitly mention that the values of `load-file-rep-suffixes',
and `get-load-suffixes' _also_ affect the return value.

load-suffixes
=> (".elc" ".el")

(locate-library "subr")
=> "{...}/emacs/lisp/subr.elc"

(locate-library "subr" t)
=> nil

Again, according to the docs the `t' arg should elide ".elc" and ".el"
suffixes. Still, this shouldn't cause locate-library to return nil, none the
less this is the value returned in lieu of empty string element from
`load-file-rep-suffixes'.

>> I don't think the docstring even reflects the intent of locate-library's
>> NOSUFFIX arg esp. as it doesn't appear to be _able_ to return a library name
>> sans extension when not called-interactively.
>
> Indeed, this arg only controls how the search is performed, not in which
> form the result will be returned.
>

Come on Stefan! Are you implying that (locate-library "subr" t) should return
non-nil regardless the second arg? It doesn't. If the search directs the
outcome of the result then it also controls the form returned.

Directing the search to, "not add suffixes `load-suffixes'" will not cause it to
search all but ".elc" and ".el", nor will it cause it to return the precise
library file name.

>> "When called from a program and NOSUFFIX is a boolean, string, or list of
>> strings, return LIBRARY's file-truename as if by `file-name-sans-extension'."
>
> That completely changes the meaning of this argument.

Only to the extent that:

a) The existing NOSUFFIX arg works as advertised. It doesn't, see item A above.

b) There is fixity w/re the meaning of the NOSUFFIX argument...

W/re to a and A above one can't break what is already broken.

  "He's only mostly dead." "She's only a 'lil bit pregnant"

Apropos b, you've already acknowledged that the meaning is poorly specified.
I don't understand how my patch can change the meaning of a poorly specified and
malfunctioning argument.

> Why don't you call file-name-sans-extension outside of locate-library instead,
> if you want that?
>
>        Stefan

Because a library is not a file.

Indeed, if I wanted to strip the suffix I would use `locate-file'. Which begs
the question, why can't one _add/filter_ the most appropriate extension to the
return value of locate-library if that is what is wanted?

This is the intention of my proposed patch.

I've attached a modified version of the original patch.

The existing change to the NOSUFFIX arg from the previous patch remains. This is
IMO a non-breaking semantic change.

In addition, I've added a new optional arg SHOW-COMPRESSED which allows
revealing whether the located library has the ".el[c]?.gz" extension. This arg
is applicable both as an interactive prefix arg and when called programatically.

The _ONLY_ potentially breaking change to the existing procedure I can find is
that where one supplies a non-nil argument for NOSUFFIX instead of returning
nil, it will now filter the suffix from the return result or any matching
library found. The benefit here being that it will now actually return
_something_ if there is a library-ish looking thing in the path.  This shouldn't
be a big deal esp. as the existing procedure just bails out...  albeit not
before first lying to me:

(locate-library "subr" t)
=> nil

Even though there _IS_ a "subr" library in the loadpath (maybe more than one).

Following are some more example test evaluations to give you an idea of what the
revised patch attached below is intended to accomplish:

;;; ==============================
;; These files were present in path when testing:
(directory-files "/home/MON/fnd-sbr" nil "s.*")
=> ("subr.el" "subr.el.gz" "subr.elc" "subr.elc.gz")

;; Return value from existing unpatched `locate-library':
(locate-library "subr" nil '("/home/MON/fnd-sbr"))
=> "/home/MON/fnd-sbr/subr.elc"

(locate-library "subr" "" '("/home/MON/fnd-sbr"))
=> nil ;You keep using that word. I do not think it means what you
think it means.

(locate-library "subr" t '("/home/MON/fnd-sbr/"))
=> nil  ;You make me feel so cheap and used.

;; Now with patched version and the new optional arg SHOW-COMPRESSED
(locate-library "subr" nil '("/home/MON/fnd-sbr"))
=> "/home/MON/fnd-sbr/subr.elc" ;Same as it ever was.

(locate-library "subr" t '("/home/MON/fnd-sbr"))
=> "/home/MON/fnd-sbr/subr" ;Hey, thats much better.

(locate-library "i-dont-exist" t '("/home/MON/fnd-sbr"))
=> nil ;At least you didn't lie to me. Maybe, we can still be friends?

(locate-library "subr" ".bad-ext" '("/home/MON/fnd-sbr"))
=> nil  ;Are you sure you've turned a new leaf?

(locate-library "subr" ".elc" '("/home/MON/fnd-sbr"))
=> "/home/MON/fnd-sbr/subr" ;OK, but could you be less vague?

(locate-library "subr" ".elc.gz" '("/home/MON/fnd-sbr"))
=> "/home/MON/fnd-sbr/subr" ;Apparently not.

(locate-library "subr" ".elc.gz" '("/home/MON/fnd-sbr") nil t)
=> "/home/MON/fnd-sbr/subr.elc.gz" ;So... you do grok Lempel-Ziv.

(locate-library "subr" '(".el.gz" ".elc.gz") '("/home/MON/fnd-sbr"))
=> "/home/MON/fnd-sbr/subr" ;But now which one did we match?

(locate-library "subr" '(".elc" ".elc.gz") '("/home/MON/fnd-sbr") nil t)
=> "/home/MON/fnd-sbr/subr" ;Was it most specific first?

(locate-library "subr" '(".elc.gz" ".elc") '("/home/MON/fnd-sbr"))
=>  "/home/MON/fnd-sbr/subr" ;Or, was it mostest specific firster morely?

(locate-library "subr" '(".elc.gz" ".elc") '("/home/MON/fnd-sbr") nil t)
=> "/home/MON/fnd-sbr/subr.elc.gz" ;Now we know she's a compressed lib.

;; Example of current  unpatched behavior:
(apply 'locate-library "subr" '(nil nil t))
=> "/usr/share/emacs/23.1.90/lisp/subr.elc" ;Same as it ever was.

;; Now with the newest patch.

;; In following two examples we supply the NOSUFIX arg as proof of concept that
;; NOPREFIX arg could find and filter the library file with suffix for each of
;; the file suffixes: .el, .elc, .el.gz, .elc.gz

;; Example of an interactive call;

(apply 'locate-library "subr" '(".el" nil t))
=> "/usr/share/emacs/23.1.90/lisp/subr"

(apply 'locate-library "subr" '(".el.gz" nil t))
=> "/usr/share/emacs/23.1.90/lisp/subr"

(apply 'locate-library "subr" '(".elc" nil t))
=> "/usr/share/emacs/23.1.90/lisp/subr"

(apply 'locate-library "subr" '(".elc.gz" nil t))
=> "/usr/share/emacs/23.1.90/lisp/subr"

;; Example of an interactive call with NOPREFIX as prefix arg
(apply 'locate-library "subr" '(t nil t))
=> "/usr/share/emacs/23.1.90/lisp/subr"

;; Example of an interactive call with SHOW-COMPRESSED as prefix arg.
(apply 'locate-library "subr" '(".el.gz" nil t 2))
=> "/usr/share/emacs/23.1.90/lisp/subr.el.gz"

;; Example2 of interactive call with SHOW-COMPRESSED as prefix arg.
(apply 'locate-library "subr" '(".elc.gz" nil t 2))
=> "/usr/share/emacs/23.1.90/lisp/subr.elc.gz" ;<- (assuming it exists)

;; Example3 of interactive call with SHOW-COMPRESSED as prefix arg.
(apply 'locate-library "subr" '(nil nil t 2))
=> "/usr/share/emacs/23.1.90/lisp/subr"

;; Example4 of interactive call with SHOW-COMPRESSED as prefix-arg.
;; This example shows that even where we force finding ".elc" we can't make it
;; return the library's file with a suffix.
(apply 'locate-library "subr" '(".elc" nil t 2))
=> "/usr/share/emacs/23.1.90/lisp/subr"

(let ((sfxs '(".bubba" ".el" ".elc" "" ".el.gz" ".elc.gz"))
      (in-paths '("/home/MON/fnd-sbr"))
      gthr-rslts
      tmp-rslts)
  (progn
    (push `(:booleans
            ,(dolist (l sfxs (setq show-libs (nreverse tmp-rslts)))
                     (push (if (locate-library "subr" l in-paths) t
nil) tmp-rslts)))
          gthr-rslts)
    (setq tmp-rslts nil)
    (push `(:paths-nocompress
            ,(dolist (l sfxs (setq show-libs (nreverse tmp-rslts)))
                     (push (locate-library "subr" l in-paths) tmp-rslts)))
          gthr-rslts)
    (setq tmp-rslts nil)
    (push `(:paths-w-compress
            ,(dolist (l sfxs (setq show-libs (nreverse tmp-rslts)))
                     (push (locate-library "subr" l in-paths nil t) tmp-rslts)))
          gthr-rslts)
    (setq gthr-rslts (nreverse gthr-rslts))))

;: :NOTE When empty string is provided to NOSUFFIX returns nil.
;;       Nothing new about that.

=> ((:booleans (nil t t nil t t))
    (:paths-nocompress
     (nil "/home/MON/fnd-sbr/subr" "/home/MON/fnd-sbr/subr"
      nil "/home/MON/fnd-sbr/subr" "/home/MON/fnd-sbr/subr"))
    (:paths-w-compress
     (nil "/home/MON/fnd-sbr/subr" "/home/MON/fnd-sbr/subr"
      nil "/home/MON/fnd-sbr/subr.el.gz" "/home/MON/fnd-sbr/subr.elc.gz")))

;; This last example illustrates that as we know the argument(s) to NOSUFFIX one
;; can now use `locate-library' to actually find a _precise_ library
filename(s).

;;; ==============================

--- subr.el~99304~      2010-01-19 15:34:00.000000000 -0500
+++ subr.el     2010-01-21 16:39:46.000000000 -0500
@@ -1564,7 +1564,7 @@
        (setq files (cdr files)))
       file)))

-(defun locate-library (library &optional nosuffix path interactive-call)
+(defun locate-library (library &optional nosuffix path
interactive-call show-compressed)
   "Show the precise file name of Emacs library LIBRARY.
 LIBRARY should be a relative file name of the library, a string.
 It can omit the suffix (a.k.a. file-name extension) if NOSUFFIX is
@@ -1585,17 +1585,37 @@
                                        'locate-file-completion-table
                                        load-path (get-load-suffixes)))
                     nil nil
-                    t))
-  (let ((file (locate-file library
-                          (or path load-path)
-                          (append (unless nosuffix (get-load-suffixes))
-                                  load-file-rep-suffixes))))
+                    t (if current-prefix-arg t)))
+  (let* ((lfrs (remove "" load-file-rep-suffixes))
+         (sfx  (cond ((booleanp nosuffix)
+                      (delete-dups (append lfrs (get-load-suffixes))))
+                     ((and nosuffix (stringp nosuffix))
+                      `(,nosuffix
+                        ,@(mapcar #'(lambda (z)
+                                      (concat nosuffix z))
+                                  lfrs)))
+                     ((consp nosuffix)
+                      (delete-dups (append nosuffix lfrs)))
+                     (t (append  lfrs(get-load-suffixes)))))
+         (file (locate-file library
+                            (or path load-path)
+                            sfx)))
+    (when (and file (or nosuffix (and show-compressed (not nosuffix))))
+      (setq file (file-truename file))
+      (let ((smp-gz (string-match-p ".*.gz" file)))
+        (setq file (concat (file-name-directory file)
+                           (cond ((or (not show-compressed)
+                                      (and show-compressed (not smp-gz)))
+                                  (file-name-sans-extension
+                                   (file-name-nondirectory
+                                    (file-name-sans-extension file))))
+                                 ((or (and show-compressed smp-gz) t)
+                                  (file-name-nondirectory file)))))))
     (if interactive-call
-       (if file
-           (message "Library is file %s" (abbreviate-file-name file))
-         (message "No library %s in search path" library)))
+        (if file
+            (message "Library is file %s" (abbreviate-file-name file))
+            (message "No library %s in search path" library)))
     file))
-
 
 ;;;; Specifying things to do later.

Attachment: subr.el.diff2
Description: Binary data


reply via email to

[Prev in Thread] Current Thread [Next in Thread]