With help from this group, I've written my first baby-program in Racket and 
would really appreciate any feedback on how to make it more idiomatic, 
efficient and well-formatted (I struggle with where to break lines). Thank you 
in advance.

The purpose is to fix the irregular capitalization of entries in the "Keywords" 
field of a large BibLaTeX (.bib) file. A sample entry in the input file might be

@article{Ender-2016-Review-00,
        Author = {Ender, P. B.},
        Keywords = {Book Review, Behaviorial sciences, ANALYSIS OF VARIANCE, 
experimental design},
        ...}

I want non-Keyword lines passed unchanged to the output file and each keyword 
entry (potentially multiword) changed to have only its first word capitalized. 
Thus

@article{Ender-2016-Review-00,
        Author = {Ender, P. B.},
        Keywords = {Book review, Behaviorial sciences, Analysis of variance, 
Experimental design},
        ...}


Here is what I came up with.

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
#lang racket

(define in (open-input-file "/Users/me/BibDeskPapers/oldBib.bib"))
(define out (open-output-file "/Users/me/BibDeskPapers/newBib.bib" #:exists 
'replace))
(define keyword-prefix "\tKeywords = {")

;; Return a string with only the first word capitalized and all else in lower 
case
;; Courtesy https://groups.google.com/forum/m/#!topic/racket-users/gw8Ivm5HSZQ
(provide 
 (contract-out 
  [string-upcase-first-word (-> string? string?)])) 

(define (string-upcase-first-word s) 
  (apply 
   string 
   (for/list ([c (in-string s)] 
              [i (in-naturals)]) 
     (if (= i 0) 
         (char-upcase c) 
         (char-downcase c)))))

(module+ test 
  (require rackunit) 
  (check-equal? (string-upcase-first-word "") "") 
  (check-equal? (string-upcase-first-word "Cat Dog") "Cat dog") 
  (check-equal? (string-upcase-first-word "cat dog") "Cat dog"))

;; Main program
(for ([aLine (in-lines in)])
  (cond
    [(string-prefix? aLine "\tKeywords = {") ; Identify Keywords lines
     (define keywords-as-list (string-split (string-replace aLine "\tKeywords = 
{" "") ","))
     (define cleaned-keywords (map (lambda (aString)
                                     (string-upcase-first-word
                                      (string-trim aString)))
                                   keywords-as-list))
     (display keyword-prefix out)
     (display (string-join cleaned-keywords ", ") out)
     (display "," out)
     (newline out)]
    [else (display aLine out) (newline out)]))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

Thank you again.

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to