]> git.donarmstrong.com Git - lilypond.git/commitdiff
Add new file lily-sort.scm; improve sorting in docs.
authorMark Polesky <markpolesky@yahoo.com>
Wed, 1 Jul 2009 23:21:14 +0000 (16:21 -0700)
committerCarl Sorensen <c_sorensen@byu.edu>
Fri, 17 Jul 2009 03:20:20 +0000 (21:20 -0600)
- add new file lily-sort.scm
- add "lily-sort.scm" to the ly:load list in documentation-generate.scm
- "string<?" --> "ly:string-ci<?" etc. in the document-*.scm files

scm/document-backend.scm
scm/document-functions.scm
scm/document-identifiers.scm
scm/document-markup.scm
scm/document-music.scm
scm/document-translation.scm
scm/documentation-generate.scm
scm/lily-sort.scm [new file with mode: 0644]

index d77a194d3194c3d79e0d1387d31e05bc444c27bb..18762aeba9cae1027fd6e65f8a79f20033942a04 100644 (file)
@@ -8,7 +8,7 @@
 (define (interface-doc-string interface grob-description)
   (let* ((name (car interface))
         (desc (cadr interface))
-        (props (sort (caddr interface) symbol<?))
+        (props (sort (caddr interface) ly:symbol-ci<?))
         (docfunc (lambda (pr)
                    (property->texi
                     'backend pr grob-description)))
@@ -61,7 +61,7 @@
                                     (hashq-ref iface->grob-table
                                                (car interface)
                                                '()))
-                               string<?)))))
+                               ly:string-ci<?)))))
     (make <texi-node>
       #:name name
       #:text (string-append
@@ -139,7 +139,7 @@ node."
      (cons (cons key val)  prior))
    '() (ly:all-grob-interfaces)))
 
-(set! interface-description-alist (sort interface-description-alist alist<?))
+(set! interface-description-alist (sort interface-description-alist ly:alist-ci<?))
 
 ;;;;;;;;;; check for dangling backend properties.
 (define (mark-interface-properties entry)
@@ -171,7 +171,7 @@ node."
     (map interface-doc interface-description-alist)))
 
 (define (backend-properties-doc-string lst)
-  (let* ((ps (sort (map symbol->string lst) string<?))
+  (let* ((ps (sort (map symbol->string lst) ly:string-ci<?))
         (descs (map (lambda (prop)
                       (property->texi 'backend (string->symbol prop) '())) ps))
         (texi (description-list->texi descs #f)))
index 34d406f89fca40763d05f36fd5bef0c704a5bfa3..3c7646cc791a46b808f0420e82a075f8f6a1a41c 100644 (file)
@@ -34,7 +34,7 @@
   (let* ((fdocs (map (lambda (x)
                       (document-scheme-function (car x) (cadr x) (cddr x)))
                     all-scheme-functions))
-        (sfdocs (sort fdocs string<?))) 
+        (sfdocs (sort fdocs ly:string-ci<?)))
     (make <texi-node>
       #:name "Scheme functions"
       #:desc "Primitive functions exported by LilyPond."
index 67e282bd862cd594beb8c26680ac25d0697021a2..0d6793428848f5cd589d436e2ada49a394de9687 100644 (file)
@@ -46,7 +46,7 @@
 
 
 (define (identifier<? a b)
-  (string<?
+  (ly:string-ci<?
    (symbol->string (car a))
    (symbol->string (car b))))
 
index af4a65d7c67cd51f10714d78226652e75d625562..ef99452be79b9f985d84380f37951cba7ef16c12 100644 (file)
@@ -62,7 +62,7 @@
                           "@end itemize\n"))))))
 
 (define (markup-function<? a b)
-  (string<? (symbol->string (procedure-name a)) (symbol->string (procedure-name b))))
+  (ly:string-ci<? (symbol->string (procedure-name a)) (symbol->string (procedure-name b))))
  
 (define (markup-category-doc-node category)
   (let* ((category-string (symbol->string category))
index b8190d95f441967bf17cf7ab654af91943b95f03..38960ee53102e5720c8e9d2a19267b2b26dfc6d2 100644 (file)
@@ -10,7 +10,7 @@
     #:name "Music properties"
     #:desc "All music properties, including descriptions."
     #:text
-    (let* ((ps (sort (map symbol->string all-music-properties) string<?))
+    (let* ((ps (sort (map symbol->string all-music-properties) ly:string-ci<?))
           (descs (map (lambda (prop)
                         (property->texi 'music (string->symbol prop)))
                       ps))
@@ -55,7 +55,7 @@
        (human-listify
        (sort
         (map (lambda (x) (ref-ify (symbol->string x)))
-             (cdr entry)) string<?))
+             (cdr entry)) ly:string-ci<?))
        "."
 
        "\n\n"
@@ -72,7 +72,7 @@
     #:children
     (map music-type-doc
         (sort
-         (hash-table->alist music-types->names) alist<?))))
+         (hash-table->alist music-types->names) ly:alist-ci<?))))
 
 (define (music-doc-str obj)
   (let* ((namesym  (car obj))
index 5bfc83a5383ba166cc6048e4c7d8fb47c9b03fcc..77f2abff2a5ef78a8f9f78dc9446e2624fbab7a2 100644 (file)
@@ -60,7 +60,7 @@
          ""
          (string-append
           "\n\nThis engraver creates the following layout object(s):\n\n"
-          (human-listify (map ref-ify (uniq-list (sort grobs string<?))))
+          (human-listify (map ref-ify (uniq-list (sort grobs ly:string-ci<?))))
           "."))
 
      "\n\n"
@@ -86,7 +86,7 @@
                (context-list (human-listify (map ref-ify
                                                  (sort
                                                   (map symbol->string contexts)
-                                                  string<?)))))
+                                                  ly:string-ci<?)))))
           (string-append
            "@code{" name-str "} "
            (if (equal? context-list "none")
           "")
 
        "\n\nThis context creates the following layout object(s):\n\n"
-       (human-listify (uniq-list (sort grob-refs string<?)))
+       (human-listify (uniq-list (sort grob-refs ly:string-ci<?)))
        "."
 
        (if (and (pair? props) (not (null? props)))
 (define (all-contexts-doc)
   (let* ((layout-alist
          (sort (ly:output-description $defaultlayout)
-               (lambda (x y) (symbol<? (car x) (car y)))))
-        (names (sort (map symbol->string (map car layout-alist)) string<?))
+               (lambda (x y) (ly:symbol-ci<? (car x) (car y)))))
+        (names (sort (map symbol->string (map car layout-alist)) ly:string-ci<?))
         (contexts (map cdr layout-alist)))
 
     (make <texi-node>
 (define all-engravers-list  (ly:get-all-translators))
 (set! all-engravers-list
       (sort all-engravers-list
-           (lambda (a b) (string<? (symbol->string (ly:translator-name a))
+           (lambda (a b) (ly:string-ci<? (symbol->string (ly:translator-name a))
                                    (symbol->string (ly:translator-name b))))))
 
 (define (all-engravers-doc)
     (map engraver-doc all-engravers-list)))
 
 (define (translation-properties-doc-string lst)
-  (let* ((ps (sort (map symbol->string lst) string<?))
+  (let* ((ps (sort (map symbol->string lst) ly:string-ci<?))
         (sortedsyms (map string->symbol ps))
         (propdescs
          (map
index 04b0a599426c6db713491b2d1056910cf4f8d0cf..478eb20efc13baa8620a3e59149c1b9efc9207bd 100644 (file)
@@ -17,6 +17,7 @@
 ;; todo: naming: grob vs. layout property
 
 (map ly:load '("documentation-lib.scm"
+              "lily-sort.scm"
               "document-functions.scm"
               "document-translation.scm"
               "document-music.scm"
diff --git a/scm/lily-sort.scm b/scm/lily-sort.scm
new file mode 100644 (file)
index 0000000..96e83b7
--- /dev/null
@@ -0,0 +1,116 @@
+;;;; lily-sort.scm -- improved sorting of symbols, strings, and alists.
+;;;;
+;;;; source file of the GNU LilyPond music typesetter
+;;;;
+;;;; Copyright 2009 Mark Polesky <markpolesky@yahoo.com>
+
+
+;; This file implements a LilyPond-specific character-sorting algorithm
+;; that can be used to sort lists, alists, etc. consistently and
+;; predictably throughout the source code. The primary advantage of this
+;; algorithm is that lists are sorted in a more intuitive way, which may
+;; allow users to find items faster in the documentation.
+;;
+;; As an example, a user, looking in the documentation to see if there's
+;; a function called "ly:grob?", might assume that there isn't one,
+;; since it doesn't appear before "ly:grob-alist-chain" (using the
+;; default sort).
+;;
+;; This happens because "-" comes before "?" in the default sort order.
+;; But since "?" is more likely to come at the end of a scheme symbol, a
+;; more intuitive sort can be achieved by reversing that order.
+;;
+;; Similarly, non-alphanumeric characters can be ranked in terms of how
+;; likely one will be found closer to the end of a symbol. For example,
+;; ":" is stronger separator than "-", as can be seen here:
+;;
+;; "ly:staff-symbol::print"
+;; "ly:staff-symbol-referencer::callback"
+;;
+;; Intuitively, "staff-symbol-referencer" ought to come after
+;; "staff-symbol", but since "-" comes before ":" in the default sort
+;; order, these symbols are by default listed in the opposite order.
+;;
+;; Thus the algorithm implemented here ranks the following nine
+;; characters (starting with the space character) in order from
+;; most-to-least likely to terminate a symbol: " !?<=>:-_". These nine
+;; characters are in effect "extracted" from the default order and then
+;; "prepended" to it so that they now come first. This is achieved with
+;; the function "ly:char-generic-<?".
+;;
+;; This file defines 3 case-sensitive binary comparison predicates:
+;;   ly:string<?     ly:symbol<?     ly:alist<?
+;; and their case-insensitive counterparts:
+;;   ly:string-ci<?  ly:symbol-ci<?  ly:alist-ci<?
+;;
+;; Case-insensitive predicates are recommended in general; otherwise
+;; symbols like "Y-offset" appear near the top of lists which
+;; otherwise include mostly lowercase symbols.
+
+(define (ly:char-generic-<? a b ci)
+  (let* ((init-list (string->list " !?<=>:-_"))
+         (mem-a (member a init-list))
+         (mem-b (member b init-list)))
+    (cond ((and mem-a mem-b) (< (length mem-b) (length mem-a)))
+          (mem-a #t)
+          (mem-b #f)
+          (else ((if ci char-ci<? char<?) a b)))))
+
+(define (ly:char<? a b)
+  (ly:char-generic-<? a b #f))
+
+(define (ly:char-ci<? a b)
+  (ly:char-generic-<? a b #t))
+
+(define (first-diff-chars str0 str1 ci)
+  (let find-mismatch ((a (string->list str0)) (b (string->list str1)))
+    (cond ((and (null? a) (null? b)) #f)
+          ((null? a) (cons #f (car b)))
+          ((null? b) (cons (car a) #f))
+          ((not ((if ci char-ci=? char=?) (car a) (car b)))
+              (cons (car a) (car b)))
+          (else (find-mismatch (cdr a) (cdr b))))))
+
+(define (ly:string-generic-<? a b ci)
+  (let ((mismatch (first-diff-chars a b ci)))
+    (cond ((and mismatch (car mismatch) (cdr mismatch))
+             ((if ci ly:char-ci<? ly:char<?)
+                   (car mismatch) (cdr mismatch)))
+          ((and mismatch (cdr mismatch)) #t)
+          (else #f))))
+
+(define (ly:string<? a b)
+  "Return #t if string A is less than string B in case-sensitive
+  LilyPond sort order."
+  (ly:string-generic-<? a b #f))
+
+(define (ly:string-ci<? a b)
+  "Return #t if string A is less than string B in case-insensitive
+  LilyPond sort order."
+  (ly:string-generic-<? a b #t))
+
+(define (ly:symbol<? a b)
+  "Return #t if symbol A is less than symbol B in case-sensitive
+  LilyPond sort order."
+  (ly:string<? (symbol->string a)
+               (symbol->string b)))
+
+(define (ly:symbol-ci<? a b)
+  "Return #t if symbol A is less than symbol B in case-insensitive
+  LilyPond sort order."
+  (ly:string-ci<? (symbol->string a)
+                  (symbol->string b)))
+
+(define (ly:alist<? a b)
+  "Return #t if the first key of alist A is less than the first key of
+  alist B, using case-sensitive LilyPond sort order. Keys are assumed to
+  be symbols."
+  (ly:string<? (symbol->string (car a))
+               (symbol->string (car b))))
+
+(define (ly:alist-ci<? a b)
+  "Return #t if the first key of alist A is less than the first key of
+  alist B, using case-insensitive LilyPond sort order. Keys are assumed
+  to be symbols."
+  (ly:string-ci<? (symbol->string (car a))
+                  (symbol->string (car b))))