使用racket/gui包.
https://docs.racket-lang.org/gui/
编辑器使用editor工具包.
https://docs.racket-lang.org/gui/editor-overview.html

editor.rkt
#lang racket/base
(require "editor-main.rkt")
(module+ main
(editor-main)
)
editor-main.rkt
#lang racket/gui
(provide editor-main)
(define (editor-main)
(define f
(new frame%
[label "SCAME"]
[width 200]
[height 200]))
(define c
(new editor-canvas%
[parent f]))
(define t
(new text%))
(send c set-editor t)
(send f show #t))
其中send方法定义为
(send obj-expr method-id arg ... . arg-list-expr)
首先计算obj-expr得到一个对象, 然后使用arg列表调用method-id方法.

在editor-main方法中,添加以下代码
(define (editor-main)
...
(define mb
(new menu-bar% [parent f]))
(define m-file
(new menu% [label "File"] [parent mb]))
(define m-edit
(new menu% [label "Edit"] [parent mb]))
(define mi-open
(new menu-item%
[label "Open"]
[parent m-file]
[callback
(lambda (i e)
(define path (get-file #f f))
(when path
(send t load-file path 'text)))]
[shortcut #\o]
[shortcut-prefix '(ctl)]))
(define mi-save
(new menu-item%
[label "Save"]
[parent m-file]
[callback
(lambda (i e)
(send t save-file #f 'text))]
[shortcut #\s]
[shortcut-prefix '(ctl)]))
(append-editor-operation-menu-items m-edit #f)
(send t set-max-undo-history 100)
...
)
其中menu-item属性callback的两个参数(i e)定义如下:
https://docs.racket-lang.org/gui/menu-item_.html
callback : ((is-a?/c menu-item%) (is-a?/c control-event%) . -> . any)
editor的load-file和save-file两个函数调用中的'text是文件格式.
https://docs.racket-lang.org/gui/editor___.html#%28meth._%28%28%28lib._mred%2Fmain..rkt%29._editor~3c~25~3e%29._load-file%29%29
append-editor-operation-menu-items是预设方法,位于racket/gui/base, 用来添加标准编辑器菜单项.
https://docs.racket-lang.org/gui/Editor_Functions.html?q=append-editor-operation-menu-items#%28def._%28%28lib._mred%2Fmain..rkt%29._append-editor-operation-menu-items%29%29
用(framwork)库中的racket:text%替换掉text%.

http://www.cs.yale.edu/homes/lucas.paul/posts/2017-07-31-making-an-editor.html