emacs.d/elpa/racket-mode-20200323.1739/racket/elisp.rkt
2020-03-24 18:20:37 +01:00

57 lines
1.6 KiB
Racket

#lang racket/base
(require racket/contract
racket/match
racket/port
racket/set)
(provide elisp-read
elisp-writeln
elisp-bool/c
as-racket-bool)
;;; read/write Emacs Lisp values
(define (elisp-read in)
(elisp->racket (read in)))
(define (elisp-writeln v out)
(elisp-write v out)
(newline out))
(define (elisp-write v out)
(write (racket->elisp v) out))
(define elisp-bool/c (or/c #t '()))
(define (as-racket-bool v)
;; elisp->racket "de-puns" 'nil as '() -- not #f. Use this helper to
;; treat as a boolean.
(and v (not (null? v))))
(define (elisp->racket v)
(match v
['nil '()] ;not #f -- see as-racket-bool
['t #t]
[(? list? xs) (map elisp->racket xs)]
[(cons x y) (cons (elisp->racket x) (elisp->racket y))]
[(vector s _ ...) s] ;Emacs strings can be #("string" . properties)
[v v]))
(define (racket->elisp v)
(match v
[(or #f (list)) 'nil]
[#t 't]
[(? list? xs) (map racket->elisp xs)]
[(cons x y) (cons (racket->elisp x) (racket->elisp y))]
[(? path? v) (path->string v)]
[(? hash? v) (for/list ([(k v) (in-hash v)])
(cons (racket->elisp k) (racket->elisp v)))]
[(? generic-set? v) (map racket->elisp (set->list v))]
[v v]))
(module+ test
(require rackunit)
(check-equal? (with-output-to-string
(λ () (elisp-write '(1 #t nil () (a . b) #hash((1 . 2) (3 . 4)))
(current-output-port))))
"(1 t nil nil (a . b) ((1 . 2) (3 . 4)))"))