Subject: bug#13207: lisp-mnt.el improvements

From: Jonas Bernoulli <[email-masked]>
Date: Wed, 19 Dec 2012 16:38:38 +0100

>> The 3500 packages from which I extracted metadata include all built-in
>> and fsf-elpa packages (though I did not process every library, just the
>> "main library" of each package).  The three packages affected in a
>> negative way didn't do things right, and they aren't fsf packages.
>
> OK, thanks for checking.  It sounds good then.  Can you send a "final" patch?

I have also updated the info page.

  Jonas

>From 001bdfead8d2fa19ef2b7b339ed01f8cf909257d Mon Sep 17 00:00:00 2001
From: Jonas Bernoulli <[email-masked]>
Date: Wed, 19 Dec 2012 16:32:08 +0100
Subject: [PATCH] * lisp/emacs-lisp/lisp-mnt.el: new function lm-homepage
 (lm-section-end): the end is now always before the following non-comment text
 (lm-header-multiline): continuation lines now need to be intended more than
 the first line (lm-with-file): widen and goto beginning of buffer before
 reusing current buffer

* doc/lispref/tips.texi: new header keyword Homepage, continuation
lines can use two or more spaces instead of a tab after the
semicolons
---
 doc/lispref/tips.texi       |  7 +++++--
 lisp/emacs-lisp/lisp-mnt.el | 39 +++++++++++++++++++++++++--------------
 2 files changed, 30 insertions(+), 16 deletions(-)

diff --git a/doc/lispref/tips.texi b/doc/lispref/tips.texi
index d54d91b..854ce8f 100644
--- a/doc/lispref/tips.texi
+++ b/doc/lispref/tips.texi
@@ -942,6 +942,7 @@ explains these conventions, starting with an example:
 ;; Created: 14 Jul 2010
 @group
 ;; Keywords: languages
+;; Homepage: http://example.com/foo
 
 ;; This file is not part of GNU Emacs.
 
@@ -980,8 +981,7 @@ the conventional possibilities for @var{header-name}:
 @item Author
 This line states the name and email address of at least the principal
 author of the library.  If there are multiple authors, list them on
-continuation lines led by @code{;;} and whitespace (this is easier
-for tools to parse than having more than one author on one line).
+continuation lines led by @code{;;} and a tab or at least two spaces.
 We recommend including a contact email address, of the form
 @samp{<@dots{}>}.  For example:
 
@@ -1028,6 +1028,9 @@ The name of this field is unfortunate, since people often assume it is
 the place to write arbitrary keywords that describe their package,
 rather than just the relevant Finder keywords.
 
+@item Homepage
+This line states the homepage of the library.
+
 @item Package-Version
 If @samp{Version} is not suitable for use by the package manager, then
 a package can define @samp{Package-Version}; it will be used instead.
diff --git a/lisp/emacs-lisp/lisp-mnt.el b/lisp/emacs-lisp/lisp-mnt.el
index f9a1c5d..4d210c2 100644
--- a/lisp/emacs-lisp/lisp-mnt.el
+++ b/lisp/emacs-lisp/lisp-mnt.el
@@ -208,10 +208,10 @@ If the given section does not exist, return nil."
 The HEADER is the section string marking the beginning of the
 section.  If the given section does not exist, return nil.
 
-The end of the section is defined as the beginning of the next
-section of the same level or lower.  The function
-`lisp-outline-level' is used to compute the level of a section.
-If no such section exists, return the end of the buffer."
+The section ends before the first non-comment text or the next
+section of the same level or lower; whatever comes first.  The
+function `lisp-outline-level' is used to compute the level of
+a section."
   (require 'outline)   ;; for outline-regexp.
   (let ((start (lm-section-start header)))
     (when start
@@ -229,9 +229,15 @@ If no such section exists, return the end of the buffer."
                            (beginning-of-line)
                            (lisp-outline-level))
                          level)))
-          (if next-section-found
-              (line-beginning-position)
-            (point-max)))))))
+	  (min (if next-section-found
+		   (progn (beginning-of-line 0)
+			  (unless (looking-at "")
+			    (beginning-of-line 2))
+			  (point))
+		 (point-max))
+	       (progn (goto-char start)
+		      (while (forward-comment 1))
+		      (point))))))))
 
 (defsubst lm-code-start ()
   "Return the buffer location of the `Code' start marker."
@@ -282,13 +288,8 @@ The returned value is a list of strings, one per line."
       (when res
 	(setq res (list res))
 	(forward-line 1)
-	(while (and (or (looking-at (concat lm-header-prefix "[\t ]+"))
-			(and (not (looking-at
-				   (lm-get-header-re "\\sw\\(\\sw\\|\\s_\\)*")))
-			     (looking-at lm-header-prefix)))
-		    (goto-char (match-end 0))
-		    (looking-at ".+"))
-	  (setq res (cons (match-string-no-properties 0) res))
+	(while (looking-at "^;+\\(\t\\|[\t\s]\\{2,\\}\\)\\(.+\\)")
+	  (push (match-string-no-properties 2) res)
 	  (forward-line 1)))
       (nreverse res))))
 
@@ -306,6 +307,8 @@ If FILE is nil, execute BODY in the current buffer."
 	     (emacs-lisp-mode)
 	     ,@body)
 	 (save-excursion
+	   (widen)
+	   (goto-char (point-min))
 	   ;; Switching major modes is too drastic, so just switch
 	   ;; temporarily to the Emacs Lisp mode syntax table.
 	   (with-syntax-table emacs-lisp-mode-syntax-table
@@ -489,6 +492,14 @@ absent, return nil."
       (when start
         (buffer-substring-no-properties start (lm-commentary-end))))))
 
+(defun lm-homepage (&optional file)
+  "Return the homepage in file FILE, or current buffer if FILE is nil."
+  (let ((page (lm-with-file file
+		(lm-header "\\(?:x-\\)?\\(?:homepage\\|url\\)"))))
+    (if (and page (string-match "^<.+>$" page))
+	(substring page 1 -1)
+      page)))
+
 ;;; Verification and synopses
 
 (defun lm-insert-at-column (col &rest strings)
-- 
1.8.0.1