From b23b8ae957dd57beff7141c7962fce0301b229b6 Mon Sep 17 00:00:00 2001 From: Matthew Butterick Date: Mon, 10 Oct 2016 13:31:12 -0700 Subject: [PATCH] improve jsonic --- beautiful-racket-lib/br/datum.rkt | 14 +++-- beautiful-racket-lib/br/indent.rkt | 42 +++++++++---- beautiful-racket/br/demo/jsonic/expander.rkt | 3 +- beautiful-racket/br/demo/jsonic/indenter.rkt | 59 ++++++++----------- .../br/demo/jsonic/jsonic-test.rkt | 9 +-- 5 files changed, 66 insertions(+), 61 deletions(-) diff --git a/beautiful-racket-lib/br/datum.rkt b/beautiful-racket-lib/br/datum.rkt index f7f88b9..f6b0678 100644 --- a/beautiful-racket-lib/br/datum.rkt +++ b/beautiful-racket-lib/br/datum.rkt @@ -2,15 +2,19 @@ (require (for-syntax racket/base br/syntax) br/define) (provide (except-out (all-defined-out) string->datum)) +(define (blank? str) + (or (zero? (string-length str)) + (andmap char-blank? (string->list str)))) + ;; read "foo bar" the same way as "(foo bar)" ;; otherwise "bar" is dropped, which is too astonishing (define (string->datum str) - (if (positive? (string-length str)) + (if (blank? str) + (void) (let ([result (read (open-input-string (format "(~a)" str)))]) (if (= (length result) 1) (car result) - result)) - (void))) + result)))) (define (datum? x) (or (list? x) (symbol? x))) @@ -34,5 +38,7 @@ (check-equal? (format-datum '(~a-bar-~a) #'foo #'zam) '(foo-bar-zam)) (check-equal? (format-datum (datum (~a-bar-~a)) "foo" "zam") '(foo-bar-zam)) (check-equal? (format-datum '~a "foo") 'foo) - (check-equal? (format-datum (datum ~a) "foo") 'foo) + (check-equal? (format-datum '~a "foo") 'foo) + (check-equal? (format-datum '~a "") (void)) + (check-equal? (format-datum '~a " ") (void)) (check-equal? (format-datums '(put ~a) '("foo" "zam")) '((put foo) (put zam)))) diff --git a/beautiful-racket-lib/br/indent.rkt b/beautiful-racket-lib/br/indent.rkt index 7f6ae29..373acc9 100644 --- a/beautiful-racket-lib/br/indent.rkt +++ b/beautiful-racket-lib/br/indent.rkt @@ -1,11 +1,16 @@ #lang racket/base -(require racket/class racket/gui/base racket/list) +(require racket/class + racket/gui/base + racket/list + racket/string) (provide (all-defined-out)) (module+ test + ;; todo: fix this so it can be tested on travis (require racket/gui/base rackunit) (define t (new text%)) - (define result (send t insert-port (open-input-string "foo\n ar\n m")))) + (define t-str "foo\n ar\n m") + (define result (send t insert-port (open-input-string t-str)))) (define indent-width 2) @@ -147,17 +152,28 @@ (send t insert-port (open-input-string str)) t) -(define (map-indenter indenter t) - (for/list ([line-idx (in-range (add1 (send t last-line)))]) - (indenter t (line-start t line-idx)))) +(define space-char? (λ(x) (x . char=? . #\space))) (define (test-indenter indenter t-or-str) (define t (if (string? t-or-str) (str->text t-or-str) t-or-str)) - (list->string - (append* - (for/list ([line-idx (in-range (add1 (send t last-line)))] - [indent (in-list (map-indenter indenter t))]) - ;; simulate DrR indentation - ;; by dropping leading spaces and applying new indent. - (append (make-list (or indent 0) #\space) - (dropf (line-chars t line-idx) (λ(x) (x . char=? . #\space)))))))) \ No newline at end of file + (define indented-t + (for/fold ([t-acc t]) + ([line-idx (in-range (add1 (send t last-line)))]) + ;; simulate DrR indentation + ;; by dropping leading spaces and applying new indent. + (define line-start-pos (line-start t-acc line-idx)) + (define new-indent (indenter t-acc line-start-pos)) + (define new-line-str + (list->string (append (make-list (or new-indent 0) #\space) + (dropf (line-chars t-acc line-idx) space-char?)))) + (send t-acc delete line-start-pos (add1 (line-end t-acc line-idx))) ; add1 to grab ending newline too + (send t-acc insert new-line-str line-start-pos) + t-acc)) + (send indented-t get-text)) + +(define (str->indents str) + (for/list ([line (in-list (string-split str "\n"))]) + (length (takef (string->list line) space-char?)))) + +(module+ test + (check-equal? (str->indents t-str) '(0 1 2))) \ No newline at end of file diff --git a/beautiful-racket/br/demo/jsonic/expander.rkt b/beautiful-racket/br/demo/jsonic/expander.rkt index 83cccf7..b93d58c 100644 --- a/beautiful-racket/br/demo/jsonic/expander.rkt +++ b/beautiful-racket/br/demo/jsonic/expander.rkt @@ -23,7 +23,8 @@ [(string? result) (format "~v" result)] [(list? result) (format "[~a]" (string-join (map stringify result) ", "))] [(hash? result) (format "{~a}" (string-join (for/list ([(k v) (in-hash result)]) - (format "~a: ~a" (stringify k) (stringify v))) ", "))])) + (format "~a: ~a" (stringify k) (stringify v))) ", "))] + [else ""])) (define-macro (s-val STR ...) (define s-exp-string diff --git a/beautiful-racket/br/demo/jsonic/indenter.rkt b/beautiful-racket/br/demo/jsonic/indenter.rkt index daa56d0..ed22a36 100644 --- a/beautiful-racket/br/demo/jsonic/indenter.rkt +++ b/beautiful-racket/br/demo/jsonic/indenter.rkt @@ -1,37 +1,28 @@ #lang at-exp br -(require br/indent sugar/debug) +(require br/indent) (provide indenter) -(define indent-width 2) -(define (indenter text [this-pos 0]) - ;; if line begins with }: - ;; outdent to the matching { - ;; indent to match the previous line - (define this-line (line text this-pos)) - (define this-line-end (line-end text this-line)) - (define open-braces - (- (count-char text #\{ 0 this-line-end) - (count-char text #\} 0 this-line-end))) - (and (positive? open-braces) - (* indent-width - (if ((char text (line-start-visible text this-line)) . char=? . #\{) - (sub1 open-braces) - open-braces)))) +(define indent-width 2) -#| - (define prev-line (previous-line text this-line)) - (define prev-indent (line-indent text prev-line)) - (cond - [((char text (line-start text this-line)) . char=? . #\}) - (and prev-indent (- prev-indent indent-width))] - [((char text (line-start text prev-line)) . char=? . #\{) - (+ (or prev-indent 0) indent-width)] - [else prev-indent])) -|# +(define (indenter tb [this-pos 0]) + (define this-line (line tb this-pos)) + (define prev-line (previous-line tb this-pos)) + (define prev-indent (or (line-indent tb prev-line) 0)) + (define this-indent + (cond + ;; if this line begins with }, outdent. + [((char tb (line-start-visible tb this-line)) . char=? . #\}) + (- prev-indent indent-width)] + ;; if last line begins with {, indent. + [((char tb (line-start-visible tb prev-line)) . char=? . #\{) + (+ prev-indent indent-width)] + ;; otherwise use previous indent + [else prev-indent])) + (and (exact-positive-integer? this-indent) this-indent)) (module+ test (require rackunit) - (define test-str @string-append|{ + (define test-str #<indents (test-indenter indenter test-str)) + (map (λ(x) (* x indent-width)) '(0 0 1 1 2 2 1 1 0)))) \ No newline at end of file diff --git a/beautiful-racket/br/demo/jsonic/jsonic-test.rkt b/beautiful-racket/br/demo/jsonic/jsonic-test.rkt index 642ab99..3ab155e 100644 --- a/beautiful-racket/br/demo/jsonic/jsonic-test.rkt +++ b/beautiful-racket/br/demo/jsonic/jsonic-test.rkt @@ -1,9 +1,2 @@ #lang br/demo/jsonic -{ -"string": @$(string-append "foo" "bar")$@, -{ -"array": @$(range 5)$@, -"object": @$(hash "k1" "valstring" (format "~a" 42) (hash "k1" (range 10) "k2" 42))$@ -} -// "bar" : -} \ No newline at end of file +@$ $@ \ No newline at end of file