我正在创建一个实时编码性能的程序,我想要一个基本的S表达式代码编辑器(我输入的内容在适当的语法环境中将eval
编辑为Racket代码。 / p>
由于DrRacket本身是用Racket编写的,我期望重新创建其代码编辑器的文本编辑功能将是相当轻松的,并且它将被记录,但我没有找到任何指导。到目前为止,我有以下代码:
(define frame (new frame% [label "Simple Edit"]
[width 800]
[height 800]))
(define canvas (new editor-canvas% [parent frame]))
(define text (new text%))
(send canvas set-editor text)
(send frame show #t)
(define menu-bar (new menu-bar% [parent frame]))
(define edit-menu (new menu% [label "Edit"] [parent menu-bar]))
(define execution-menu (new menu% [label "Execution"] [parent menu-bar]))
(new menu-item% [label "Run"]
[parent execution-menu]
[callback (λ (mi e) (update (send text get-text)))]
[shortcut #\R]
[shortcut-prefix '(cmd)])
(append-editor-operation-menu-items edit-menu #f)
(define delta (make-object style-delta% 'change-size 14))
(send delta set-face "Menlo")
(send text change-style delta)
有了这个,我已经将字体及其大小设置为令人满意的,并且复制和粘贴操作等工作。但是有很多意想不到的行为,例如:
我不想重新发明轮子,所以我用Google搜索但无济于事,尝试查看DrRacket源代码(这对于我对语言的理解仍然有限而过于复杂),等等。似乎是一个很好的解释,使用GUI工具包本身(不仅仅是参考),我上面粘贴的东西给我带来了大量的试错,所以我不期待实现所有这些基本的文本编辑手工。
如果有人有一个项目源代码可以说明如何完成这项工作,一些已经解决它的软件包,或者一些能让我走上正轨的指针,我们将不胜感激!
答案 0 :(得分:2)
DrRacket大量使用framework
库,它是构建在racket/gui
之上的GUI组件的更高级工具包。支持语法突出显示的编辑器组件接口是color:text<%>
,它支持基于您为start-colorer
方法提供的任意lexing函数的相当高级,完全可自定义的语法突出显示。 color:text<%>
接口本身基于text:basic<%>
的顶部,它也来自framework
,并实现了您描述的一些与非着色相关的编辑行为。
由于color:text<%>
是一个接口,因此无法直接使用,但framework
也提供color:text%
,这是一个可以像任何其他组件一样创建和操作的具体实现。如果您需要更多灵活性,还有color:text-mixin
,它允许向任意文本编辑器类添加color:text<%>
功能。 text:basic<%>
和text:basic%
形式存在framework
的相似之处。
color:text<%>
的源代码是text:basic-mixin
的一部分。您还可以在DrRacket中浏览源代码而无需克隆任何内容 - 只需右键单击模块名称并选择打开main.rkt 或类似,或使用文件→打开需求路径。 .. 菜单选项并键入已安装的模块的路径以打开其源代码。
为了更好地了解如何使用#lang
的语法着色功能,查看the gui-lib
package, available on GitHub here以获得实现所需协议的非常简单的词法分析器或{ {3}}用于DrRacket实际使用的更复杂的词法分析器,以突出显示球拍代码。
最后,还值得注意的是,通过使用#lang
机制,所有这些实际上都可以在DrRacket本身中自定义,因此自定义framework
可以实际提供自己的Lexers,DrRacket将使用。这显然需要最少重新发明轮子,但听起来你想完全实现自己的编辑器,在这种情况下使用new
中的组件将是你最好的选择。
答案 1 :(得分:2)
编辑部分(不是“运行”部分)的功能由framework
库中的racket:text%
类提供。
#lang racket/gui
(require framework)
(define frame
(new frame% [label "Simple Editor"] [width 800] [height 800]))
(define text-editor
(new racket:text%))
(define canvas
(new editor-canvas% [parent frame] [editor text-editor]))
(send frame show #true)
它负责语法高亮,paren-matching,双击s-expression和缩进。问题中的代码是添加“运行”功能的开始,因为回调函数可以在应该运行时获取文本。所以现在你需要的只是一个可以获取一段文本并运行它的函数。为此,您可以使用racket/sandbox
中的make-module-evaluator
。
(require racket/sandbox)
(define (run-text str)
(define repl-ev
(parameterize ([sandbox-output (current-output-port)]
[sandbox-error-output (current-error-port)])
(make-module-evaluator str)))
(void))
然后你可以在你的回调函数中使用run-text
,如下所示:
[callback (λ (mi e) (run-text (send text-editor get-text)))]
当前设置的方式,运行模块会在DrRacket的交互窗口中打印结果。你可能想要自己的交互窗口,我不知道该怎么做。
答案 2 :(得分:-1)
(需要框架) (要求(仅在mzlib / string中从字符串中读取所有expr-> string))
(定义ns(make-base-namespace)) (eval'{require scheme)ns)
(定义框架 (新帧%[标签“简单编辑器”] [宽度800] [高度200])) (定义文本编辑器 (新球拍:文本%) (定义画布 (新的编辑器画布%[父级框架(最小高度120)[编辑器文本编辑器]))
(发送帧显示#true)
(定义text-editor2 (新球拍:文本%) (定义canvas2 (新的编辑器画布%[父框架](最小高度120)[编辑器文本编辑器2]))
(定义hpa(新的水平面板% (父帧)(对齐方式'(中心居中)))
(定义按钮评估 (新按钮%(父级HPA) (标签为“评估者”) (样式'(border)) (回调(lambda(b e); b =按钮,e =事件 (发送文本编辑器2擦除) (让[[L(全部从字符串读取(发送文本编辑器get-text))))) (对于每个(lambda(expr) (发送text-editor2 insert(expr-> string(eval expr ns))) (发送text-editor2插入“ \ n”)) L))))))