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