raart/size.rkt

86 lines
2.2 KiB
Racket
Raw Normal View History

2018-01-01 23:33:27 +00:00
#lang racket/base
(require racket/match
racket/list
racket/system
ansi)
(define stty-minus-f-arg-string
(case (system-type 'os)
((macosx) "-f")
(else "-F")))
(define (read-until ip char)
(define byte (char->integer char))
(apply bytes
(let loop ()
(match (read-byte ip)
[(== byte) empty]
[next (cons next (loop))]))))
2018-01-01 23:59:14 +00:00
(define (bytes->number bs)
(string->number (bytes->string/utf-8 bs)))
(define default-tty "/dev/tty")
(struct term (f in out))
(define (open-term #:tty [tty default-tty])
2018-01-01 23:33:27 +00:00
(system* "/bin/stty"
stty-minus-f-arg-string
2018-01-01 23:59:14 +00:00
tty
2018-01-01 23:33:27 +00:00
"raw"
"-echo")
(define-values (in out)
2018-01-01 23:59:14 +00:00
(open-input-output-file tty #:exists 'update))
(term tty in out))
(define (close-term t)
(match-define (term f in out) t)
(close-input-port in)
(close-output-port out)
(system* "/bin/stty"
stty-minus-f-arg-string
f
"cooked"
"echo"))
(define (with-term f #:tty [tty default-tty])
(define t (open-term #:tty tty))
(define (close!) (close-term t))
(with-handlers ([exn:fail? (λ (x) (close!) (raise x))])
(begin0 (f t) (close!))))
(define (with-term* t f)
(if t (f t) (with-term f)))
(define (screen-size [t #f])
(with-term* t
(λ (t)
(match-define (term _ in out) t)
(write-bytes #"\e[18t" out) (flush-output out)
2018-01-01 23:33:27 +00:00
(match (read-until in #\;)
[#"\e[8"
(define row-s (read-until in #\;))
(define col-s (read-until in #\t))
(values (bytes->number row-s)
(bytes->number col-s))]
2018-01-01 23:59:14 +00:00
[x (error 'screen-size "Something weird happened, got ~e" x)]))))
2018-01-01 23:33:27 +00:00
2018-01-01 23:59:14 +00:00
(define (cursor-position [t #f])
(with-term* t
(λ (t)
(match-define (term _ in out) t)
(display (position-report-request) out) (flush-output out)
(match (read-bytes 2 in)
[#"\e["
(define row-s (read-until in #\;))
(define col-s (read-until in #\R))
(values (bytes->number row-s)
(bytes->number col-s))]
[x (error 'cursor-position "Something weird happened, got ~e" x)]))))
2018-01-01 23:33:27 +00:00
(module+ main
2018-01-01 23:59:14 +00:00
(with-term
(λ (t)
(screen-size t)
(cursor-position t))))