With Carl's help, I've created a new file that contains procedures
for sorting lists and alists according to a specific algorithm
that generates more intuitively-ordered lists, which will make it
a lot easier to locate things in the docs, for example.

I've attached the file here, but I haven't made a patch, because I
need to know a) if anyone wants to suggest any alterations before
Carl applies it, and b) precisely where should I enter 
"lily-sort.scm" in the file "lily.scm" (there are procedures
defined publicly).

I'm interested in feedback regarding my selection and order of
ranked non-alphanumeric characters ( !?<=>:-_).

Also I think the initial comments are kind of lengthy, maybe
someone can comment on that, too.

Thanks.
- Mark



      
;; lily-sort.scm
;;
;; LilyPond-specific sorting of symbols, strings, and alists.
;;
;; (c) 2009 Mark Polesky
;;
;; 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: " !?<=>:-_". That order
;; is defined in the "init-list" binding of the function
;; "ly:char-compare".
;;
;; Publicly defined binary predicates include:
;;   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-compare 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-compare a b #f))

(define (ly:char-ci<? a b)
  (ly:char-compare a b #t))

(define (first-diff-chars str0 str1 ci)
  (let loop ((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 (loop (cdr a) (cdr b))))))

(define (ly:string-compare 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-public (ly:string<? a b)
  "Return #t if string A is less than string B in case-sensitive
  LilyPond sort order."
  (ly:string-compare a b #f))
 
(define-public (ly:string-ci<? a b)
  "Return #t if string A is less than string B in case-insensitive
  LilyPond sort order."
  (ly:string-compare a b #t))

(define-public (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-public (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-public (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-public (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))))
_______________________________________________
lilypond-devel mailing list
lilypond-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/lilypond-devel

Reply via email to