;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; ;;; schematic-format.scm ;;; ;;; This is a program for formatting Scheme source. Currently, that ;;; means slightly opinionated autoindentation of R7RS forms. ;;; ;;; See this project's README for more information. ;;; ;;; Copyright (c) 2013-2014, Evan Hanson ;;; See LICENSE for details. ;;; (import (schematic format) (schematic process) (scheme base) (scheme char) (scheme file) (scheme process-context) (scheme read) (scheme write)) (define program-version "0.1.3") (define (every? pred? lst) (or (null? lst) (and (pred? (car lst)) (every? pred? (cdr lst))))) ;; XXX Drops the error's irritants' tail. (define (prefix-error e msg) (error (string-append msg ": " (error-object-message e)) (car (error-object-irritants e)))) ;; The default behavior for keywords is to use the offset given by ;; `keyword-indent`, but that may be overridden by a user-specified file ;; containing custom indentation rules. (define keyword-indentation-function (make-parameter keyword-indent)) ;; ;; An indentation file contains a single S-expression, which should be a ;; list of indentation rules where each rule is one of the following ;; forms: ;; ;; (keyword . integer) ;; (keyword integer ...) ;; (define read-indentation-file (let ((valid-indentation-rule? (lambda (p) (or (and (list? p) (every? integer? (cdr p))) (and (pair? p) (integer? (cdr p))))))) (lambda (path) (guard (e ((prefix-error e "Unable to read indentation file"))) (map (lambda (p) (cond ((valid-indentation-rule? p) p) ((error "Invalid indentation rule" p)))) (let ((forms (with-input-from-file path read))) (cond ((list? forms) forms) ((error "Not an alist" path))))))))) (for-each (lambda (option) (cond ((member option '("-v" "--version")) (display program-version) (newline) (exit)) ((member option '("-h" "--help")) (display "Usage: ") (display (car (command-line))) (display " [indent-file]") (newline) (exit)) (else (with-exception-handler error-exit (lambda () (let ((rules (read-indentation-file option))) (keyword-indentation-function (lambda (keyword eol?) (cond ((assq keyword rules) => cdr) ((keyword-indent keyword eol?)) (else #f)))))))))) (cdr (command-line))) (format-scheme (current-input-port) (current-output-port) (keyword-indentation-function))