diff1-example.hl.rkt (3806B)
1 #lang hyper-literate #:♦ racket/base 2 ♦;(dotlambda/unhygienic . racket/base) 3 4 ♦title{Highlighting added, removed and existing parts in literate programs} 5 6 ♦defmodule[hyper-literate/diff1] 7 8 Highly experimental. Contains bugs, API may change in the future. 9 10 ♦defform[(hlite name pat . body)]{ 11 12 Like ♦racket[chunk], but highlights parts of the ♦racket[body] according to 13 the pattern ♦racket[pat]. 14 15 The ♦racket[pat] should cover the whole ♦racket[body], which can contain 16 multiple expressions. The ♦racket[pat] can use the following symbols: 17 18 ♦itemlist[ 19 ♦item{♦racket[=] to indicate that the following elements are ``normal'' and 20 should not be highlighted in any special way.} 21 ♦item{♦racket[/] to indicate that the following elements were already 22 existing in previous occurrences of the code (the part is dimmed)} 23 ♦item{♦racket[+] to indicate that the following elements are new (highlighted 24 in green)} 25 ♦item{♦racket[-] to indicate that the following elements are removed 26 (highlighted in red). Removed elements are also removed from the actual 27 executable source code. If a removed element contains one or more normal, new 28 or dimmed elements, these children are spliced in place of the removed 29 element.} 30 ♦item{Other symbols are placeholders for the elements}] 31 32 In the following example, the ♦racket[1] is highlighted as removed (and will 33 not be present in the executable code), the ♦racket[π] is highlighted as 34 added, and the rest of the code is dimmed: 35 36 ♦codeblock|{ 37 #lang hyper-literate #:♦ racket/base 38 ♦hlite[<my-code> {/ (def args (_ - _ + _ / . _))} 39 (define (foo v) 40 (+ 1 π . v))]}| 41 42 It produces the result shown below:} 43 44 ♦require[hyper-literate/diff1] 45 46 ♦hlite[<my-code> {/ (def args (_ - _ + _ / . _))} 47 (define (foo v) 48 (+ 1 π . v))] 49 50 ♦section{Example} 51 52 You can look at the source code of this document to see how this example is 53 done. 54 55 ♦require[hyper-literate/diff1] 56 57 We define the function foo as follows: 58 59 ♦chunk[<foo> 60 (define (foo v) 61 (+ 1 v))] 62 63 However, due to implementation details, we need to add ♦racket[π] to this 64 value: 65 66 ♦hlite[|<foo'>| {/ (def args (_ _ + _ / . _))} 67 (define (foo v) 68 (+ 1 π . v))] 69 70 In order to optimise the sum of ♦racket[1] and ♦racket[π], we extract the 71 computation to a global helper constant: 72 73 74 ♦hlite[|<foo''>| {+ _ _ / (def args '(+ a - b + c d . e) (_ - _ _ + _ / _)) = _} 75 (define π 3.1414592653589793) 76 (define one-pus-π (+ 1 π)) 77 (define (foo v) 78 '(a b c d . e) 79 (+ 1 π one-pus-π v))0] 80 81 ♦hlite[|<www>| (/ (quote (+ a - b + c d . e)) 82 (quote (+ a - b + c d . e)) 83 (= quote (+ a - b + c d . e)) 84 (quote (quote (+ a - b + c d . e)))) 85 '(a b c d . e) 86 (quote (a b c d . e)) 87 (quote (a b c d . e)) 88 ''(a b c d . e)] 89 90 The whole program is therefore: 91 92 ♦hlite[|<aaa>| {- a + b = c / d} 93 1 2 3 4] 94 95 ♦hlite[<bbb> {- (+ a - b = c)} 96 (x y z)] 97 98 ♦hlite[<ccc> {(z - (+ a - b / . c))} 99 (0 (x y . z))] 100 101 ♦hlite[<ddd> {(z - ((+ a a - b b / . c)))} 102 (0 ((x x y yy . z)))] 103 104 ♦hlite[<eee> {(z - ((+ a a - b b / . c)))} 105 (0 ((x x y yy 106 . z)))] 107 108 ♦chunk[<*> 109 (require rackunit) 110 |<foo''>| 111 (check-= (foo 42) (+ 42 1 3.1414592653589793) 0.1) 112 (check-equal? (list <www>) 113 '((a c d . e) 114 (a c d . e) 115 (a c d . e) 116 (quote (a c d . e)))) 117 (check-equal? '(<aaa>) '(2 3 4)) 118 (check-equal? '(0 <bbb> 1) '(0 x z 1)) 119 (check-equal? '<ccc> '(0 x . z)) 120 (check-equal? '<ddd> '(0 x x . z))]