all messages for Guix-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
From: Herman Rimm via Guix-patches via <guix-patches@gnu.org>
To: 70800@debbugs.gnu.org
Subject: [bug#70800] [PATCH] scripts: style: Add 'alphabetical-sort' option.
Date: Mon,  2 Sep 2024 20:58:05 +0200	[thread overview]
Message-ID: <20240902185808.12842-1-herman@rimm.ee> (raw)
In-Reply-To: <8e0df2707343eaee0bf39fa06fcdd5bc5cd9fba2.1714992109.git.herman@rimm.ee>

* guix/scripts/style.scm (show-help): Describe option.
(order-packages): Add procedure.
(format-whole-file): Add 'order?' argument.
(%options): Add 'alphabetical-sort' option.
(guix-style): Alphabetically order packages in files.
* tests/guix-style.sh: Test alphabetical ordering.
* doc/guix.texi (Invoking guix style): Document option.

Change-Id: I4aa7c0bd0b6d42529ae7d304587ffb10bf5f4006
---
 doc/guix.texi          |  7 ++++
 guix/scripts/style.scm | 73 ++++++++++++++++++++++++++++++++++++++----
 tests/guix-style.sh    | 26 +++++++++++++++
 3 files changed, 100 insertions(+), 6 deletions(-)

diff --git a/doc/guix.texi b/doc/guix.texi
index f7dbe246a9..6f6f952f96 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -15216,6 +15216,13 @@ configuration (you need write permissions for the file):
 guix style -f /etc/config.scm
 @end example
 
+@item --alphabetical-sort
+@itemx -A
+Place the top-level package definitions in the given files in
+alphabetical order.  Package definitions with matching names are placed
+with versions in descending order.  This option only has an effect in
+combination with @option{--whole-file}.
+
 @item --styling=@var{rule}
 @itemx -S @var{rule}
 Apply @var{rule}, one of the following styling rules:
diff --git a/guix/scripts/style.scm b/guix/scripts/style.scm
index 1802b854d0..73e3feadee 100644
--- a/guix/scripts/style.scm
+++ b/guix/scripts/style.scm
@@ -1,5 +1,6 @@
 ;;; GNU Guix --- Functional package management for GNU
 ;;; Copyright © 2021-2024 Ludovic Courtès <ludo@gnu.org>
+;;; Copyright © 2024 Herman Rimm <herman@rimm.ee>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -29,6 +30,7 @@
 
 (define-module (guix scripts style)
   #:autoload   (gnu packages) (specification->package fold-packages)
+  #:use-module (guix combinators)
   #:use-module (guix scripts)
   #:use-module ((guix scripts build) #:select (%standard-build-options))
   #:use-module (guix ui)
@@ -485,11 +487,62 @@ (define* (format-package-definition package
 ;;; Whole-file formatting.
 ;;;
 
-(define* (format-whole-file file #:rest rest)
-  "Reformat all of FILE."
+(define (order-packages lst)
+  "Return LST, a list of top-level expressions and blanks, with
+top-level package definitions in alphabetical order.  Packages which
+share a name are placed with versions in descending order."
+  (define (package-name pkg)
+    (match pkg
+      ((('define-public _ expr) _ ...)
+       (match expr
+         ((or ('package _ ('name name) _ ...)
+              ('package ('name name) _ ...))
+          name)
+         (_ #f)))
+      (_ #f)))
+
+  (define (package-version pkg)
+    (match pkg
+      ((('define-public _ expr) _ ...)
+       (match expr
+         ((or ('package _ _ ('version version) _ ...)
+              ('package _ ('version version) _ ...))
+          version)
+         (_ #f)))
+      (_ #f)))
+
+  (define (package>? lst1 lst2)
+    (let ((name1 (package-name lst1))
+          (name2 (package-name lst2))
+          (version1 (package-version lst1))
+          (version2 (package-version lst2)))
+      (and name1 name2 (or (string>? name1 name2)
+                           (and (string=? name1 name2)
+                                version1
+                                version2
+                                (version>? version2 version1))))))
+
+        ;; Group define-public with preceding blanks and defines.
+  (let ((lst (fold2 (lambda (expr tail head)
+                      (let ((head (cons expr head)))
+                        (match expr
+                          ((? blank?)
+                           (values tail head))
+                          (('define _ ...)
+                           (values tail head))
+                          (_ (values (cons head tail) '())))))
+                    '() '() lst)))
+    (reverse (concatenate (sort! lst package>?)))))
+
+(define* (format-whole-file file order? #:rest rest)
+  "Reformat all of FILE. When ORDER? is true, top-level package definitions
+are put in alphabetical order."
   (with-fluids ((%default-port-encoding "UTF-8"))
-    (let ((lst (call-with-input-file file read-with-comments/sequence
-                                     #:guess-encoding #t)))
+    (let* ((lst (call-with-input-file file read-with-comments/sequence
+                                      #:guess-encoding #t))
+           (lst (if order?
+                    (order-packages lst)
+                    lst)))
       (with-atomic-file-output file
         (lambda (port)
           (apply pretty-print-with-comments/splice port lst
@@ -517,6 +570,9 @@ (define %options
         (option '(#\f "whole-file") #f #f
                 (lambda (opt name arg result)
                   (alist-cons 'whole-file? #t result)))
+        (option '(#\A "--alphabetical-sort") #f #f
+                (lambda (opt name arg result)
+                  (alist-cons 'order? #t result)))
         (option '(#\S "styling") #t #f
                 (lambda (opt name arg result)
                   (alist-cons 'styling-procedure
@@ -560,7 +616,7 @@ (define (show-help)
   (display (G_ "
   -S, --styling=RULE     apply RULE, a styling rule"))
   (display (G_ "
-  -l, --list-stylings   display the list of available style rules"))
+  -l, --list-stylings    display the list of available style rules"))
   (newline)
   (display (G_ "
   -n, --dry-run          display files that would be edited but do nothing"))
@@ -575,6 +631,9 @@ (define (show-help)
   (newline)
   (display (G_ "
   -f, --whole-file       format the entire contents of the given file(s)"))
+  (display (G_ "
+  -A, --alphabetical-sort
+                         place the contents in alphabetical order as well"))
   (newline)
   (display (G_ "
   -h, --help             display this help and exit"))
@@ -618,7 +677,9 @@ (define (parse-options)
               (warning (G_ "'--styling' option has no effect in whole-file mode~%")))
             (when (null? files)
               (warning (G_ "no files specified, nothing to do~%")))
-            (for-each format-whole-file files))
+            (for-each
+              (cute format-whole-file <> (assoc-ref opts 'order?))
+              files))
           (let ((packages (filter-map (match-lambda
                                         (('argument . spec)
                                          (specification->package spec))
diff --git a/tests/guix-style.sh b/tests/guix-style.sh
index 2de879d5e3..9333139435 100644
--- a/tests/guix-style.sh
+++ b/tests/guix-style.sh
@@ -58,6 +58,24 @@ cat > "$tmpfile" <<EOF
   ;; The services.
   (services
    (cons (service mcron-service-type) %base-services)))
+;; Incomplete package definitions in alphabetical order.
+
+(define-public pkg
+  (package
+    (name "bar")
+    (version "2")))
+
+;; The comment below belongs to the foo package.
+(define-public pkg
+  (package
+    (name "bar")
+    (version "1")))
+;; Incomplete package definitions in alphabetical order.
+
+(define-public pkg
+  (package
+    (name "foo")
+    (version "2")))
 EOF
 
 cp "$tmpfile" "$tmpfile.bak"
@@ -78,3 +96,11 @@ test "$initial_hash" != "$(guix hash "$tmpfile")"
 
 guix style -f "$tmpfile"
 test "$initial_hash" = "$(guix hash "$tmpfile")"
+
+# Swap foo and bar packages.
+sed -i "$tmpfile" -e 's/"foo"/"bar"/g'
+sed -i "$tmpfile" -e '0,/"bar"/{s//"foo"/}'
+test "$initial_hash" != "$(guix hash "$tmpfile")"
+
+guix style -fA "$tmpfile"
+test "$initial_hash" = "$(guix hash "$tmpfile")"
-- 
2.45.2





  parent reply	other threads:[~2024-09-02 18:59 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-05-06 10:50 [bug#70800] [PATCH] scripts: style: Add 'order' option to alphabetically order file Herman Rimm via Guix-patches via
2024-05-25 14:14 ` Ludovic Courtès
2024-05-31 15:36   ` Simon Tournier
2024-06-26 21:32   ` Ludovic Courtès
2024-07-04 15:55 ` [bug#70800] [PATCH v2] scripts: style: Add 'alphabetical-sort' option Herman Rimm via Guix-patches via
2024-07-18 15:12   ` Ludovic Courtès
2024-09-02 18:58 ` Herman Rimm via Guix-patches via [this message]
2024-09-03  9:50   ` bug#70800: [PATCH] " Ludovic Courtès

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20240902185808.12842-1-herman@rimm.ee \
    --to=guix-patches@gnu.org \
    --cc=70800@debbugs.gnu.org \
    --cc=herman@rimm.ee \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this external index

	https://git.savannah.gnu.org/cgit/guix.git

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.