Start tracking the listing module.

This commit is contained in:
Dominik Pantůček 2023-03-13 19:30:59 +01:00
parent 0d1b429e04
commit b026949266
2 changed files with 99 additions and 1 deletions

76
listing.scm Normal file
View file

@ -0,0 +1,76 @@
(module
listing (print-source-listing listing-tests!)
(import scheme
testing
(chicken base)
(chicken string)
(chicken format))
;; Returns the number of digits required to represent a given number
;; in decimal format.
(define (number-digits number)
(let loop ((number (abs number))
(digits 0))
(if (= number 0)
(if (= digits 0)
1
digits)
(loop (quotient number 10)
(+ digits 1)))))
;; Formats line number padding it with spaces from the left for
;; alignment with number of given maximum number of digits and
;; appends ordinal dot and space.
(define (format-line-number number digits)
(let loop ((args (list (sprintf "~A. " number)))
(spaces (- digits (number-digits number))))
(if (<= spaces 0)
(string-intersperse args "")
(loop (cons " " args)
(- spaces 1)))))
;; Returns true if given line is near the target line.
(define (line-near-target? line target context)
(or (< context 0)
(<= (abs (- line target)) context)))
(define (print-source-listing lines highlights context hl-pre hl-post ctx-pre ctx-pre ellipsis)
(let ((digits (number-digits (length lines))))
(let loop ((lines lines)
(number 1))
(when (not (null? lines))
(print (format-line-number number digits) (car lines))
(loop (cdr lines)
(+ number 1))))))
;; Performs self-tests of the listing module.
(define (listing-tests!)
(run-tests
listing
(test-eq? number-digits (number-digits 0) 1)
(test-eq? number-digits (number-digits 1) 1)
(test-eq? number-digits (number-digits 9) 1)
(test-eq? number-digits (number-digits 10) 2)
(test-eq? number-digits (number-digits 999) 3)
(test-equal? format-line-number (format-line-number 5 3) " 5. ")
(test-true line-near-target? (line-near-target? 4 5 -1))
(test-true line-near-target? (line-near-target? 4 5 1))
(test-true line-near-target? (line-near-target? 1 5 10))
(test-false line-near-target? (line-near-target? 4 5 0))
))
)
(import listing)
(print-source-listing
'("asdf" "qwer")
'(1)
5
"\x1b[31;1m" "\x1b[0m"
"\x1b[33;1m" "\x1b[0m"
"\x1b[30;1m...\x1b[0m")
(listing-tests!)

View file

@ -22,7 +22,7 @@
;; ;;
(module (module
testing testing
(test-eq? test-equal? test-exn run-tests) (test-eq? test-equal? test-exn test-true test-false run-tests)
(import scheme (import scheme
(chicken condition)) (chicken condition))
@ -59,6 +59,28 @@
(error 'test-equal? (sprintf "~A expression=~S expected-result=~S result=~S" (error 'test-equal? (sprintf "~A expression=~S expected-result=~S result=~S"
'name 'expression expected-result result))))))) 'name 'expression expected-result result)))))))
;; Test passes if the expression evaluates to #t, raises exception
;; otherwise.
(define-syntax test-true
(syntax-rules ()
((_ name expression)
(let ((result expression))
(if (eq? result #t)
(display ".")
(error 'test-true (sprintf "~A expression=~S result=~S"
'name 'expression result)))))))
;; Test passes if the expression evaluates to #f, raises exception
;; otherwise.
(define-syntax test-false
(syntax-rules ()
((_ name expression)
(let ((result expression))
(if (eq? result #f)
(display ".")
(error 'test-true (sprintf "~A expression=~S result=~S"
'name 'expression result)))))))
;; Passes if the-test raises an exception ;; Passes if the-test raises an exception
(define-syntax test-exn (define-syntax test-exn
(syntax-rules () (syntax-rules ()