【问题标题】:Basic code editor functionality in RacketRacket 中的基本代码编辑器功能
【发布时间】:2016-10-01 17:26:33
【问题描述】:

我正在创建一个用于实时编码性能的程序,我想要一个基本的 S 表达式代码编辑器(我输入的内容将是 evaled 在适当的句法上下文中作为球拍代码)。

由于 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)

有了这个,我将字体及其大小设置为一个合适的,复制和粘贴操作等工作。但是有很多意想不到的行为,比如:

  • 按修饰符+字母组合键仍会插入字母,而不是忽略它。
  • 按 alt+left 或 cmd+left(Mac 用户)会将插入符号移动单个字符而不是单词或移动到边缘。
  • 双击不会选择单词。

我不想重新发明轮子,所以我努力搜索但无济于事,尝试查看 DrRacket 源代码(这对于我对语言的理解仍然有限来说太复杂了)等等。没有似乎是关于使用 GUI 工具包本身的一个很好的解释(这不仅仅是参考),我上面粘贴的内容让我进行了大量的反复试验,所以我不期待实施所有这些基本的文本编辑都是手工完成的。

如果有人有一个项目源代码来举例说明如何完成这项工作,一些解决了它的包,或者一些能让我走上正轨的指针,我们将不胜感激!

【问题讨论】:

  • 您是否查看过 DrRacket 插件文档 (docs.racket-lang.org/tools/index.html)?我自己没有读过,但它似乎可以教drracket的细节。此外,该页面还建议您检查框架 (docs.racket-lang.org/framework/index.html) - 它建立在您开始使用的球拍/gui 库之上。
  • 不幸的是,我不知道使用 Racket gui 框架的“记事本”克隆。然而,这个例子比 DrRacket 短,所以看看源代码并询问是否有什么不合理的地方(注意:我已经有几年没有测试过了)。 github.com/soegaard/bracket/blob/master/gui/racket-cas.rkt#L411
  • @MattPeerson 谢谢,framework 确实是一个很棒的提示!
  • @soegaard 谢谢,如果我决定进一步定制,我可能会使用你的代码作为参考。

标签: racket code-editor


【解决方案1】:

编辑部分(不是“运行”部分)的功能由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)

这会处理语法高亮、括号匹配、双击 s 表达式和缩进。您在问题中的代码是添加“运行”功能的开始,因为回调函数可以在应该运行时获取文本。所以现在你所需要的只是一个可以获取一段文本并运行它的函数。为此,您可以使用来自racket/sandboxmake-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 的交互窗口中打印结果。你可能想要你自己的交互窗口,我不知道该怎么做。

【讨论】:

  • 非常感谢! racket:text% 课程正是我所需要的!我知道它在某个地方,我只是不知道如何找到它。 :) 实际上它的执行代码部分已经在我的代码的其他地方解决了,但是你的方法不同,所以我会检查并比较。
【解决方案2】:

DrRacket 大量使用 framework 库,这是一个构建在 racket/gui 之上的更高级别的 GUI 组件工具包。支持语法高亮的编辑器组件接口是color:text<%>,它支持相当高级的、完全可定制的语法高亮,基于您提供给start-colorer 方法的任意词法分析功能。 color:text<%> 接口本身是基于text:basic<%> 之上的,text:basic<%> 也来源于framework,并实现了你描述的一些非着色相关的编辑行为。

由于color:text<%> 是一个接口,它不能直接使用,但framework 还提供了color:text%,一个可以像任何其他组件一样创建和操作的具体实现。如果您需要更大的灵活性,还有color:text-mixin,它允许将color:text<%> 功能添加到任意文本编辑器类。 text:basic<%>text:basic%text:basic-mixin 的形式存在相似之处。

framework 的源代码是the gui-lib package, available on GitHub here 的一部分。您还可以在 DrRacket 中浏览源代码,而无需克隆任何内容——只需右键单击模块名称并选择 Open main.rkt 或类似名称,或使用 File → Open Require Path。 .. 菜单选项并键入您已安装的模块的路径以打开其源代码。

为了更好地了解如何使用 color:text<%> 的语法着色功能,查看 syntax-color/default-lexer 以了解实现所需协议的非常简单的词法分析器或查看 syntax-color/racket-lexer 以了解DrRacket 实际使用更复杂的词法分析器来突出显示 Racket 代码。

最后,还值得注意的是,所有这些实际上都可以通过使用#lang 机制在 DrRacket 本身内进行自定义,因此自定义 #langs 实际上可以提供自己的词法分析器,即 DrRacket将使用。这显然需要最少的重新发明轮子,但听起来您想完全实现自己的编辑器,在这种情况下,使用来自 framework 的组件将是您最好的选择。

【讨论】:

  • 谢谢!那个framework我不知道,很高兴知道!然而,当我尝试阅读参考资料时,我遇到了与 GUI 工具包参考资料相同的问题,即它没有解释它的用途,所以我对如何实现我想要的东西有点茫然。关于使用 DrRacket 本身,我正在使用它,但我需要一个单独的接口用于它的实时编码部分;这样我就可以即时更新执行代码。
  • 是的,framework 引用可能会造成混淆。很多类都没有记录,除了它们的 mixin 之外,mixin 可以引导你到处追逐。
【解决方案3】:

lang 球拍/gui

(需要框架) (require (only-in mzlib/string read-from-string-all expr->string))

(定义 ns (make-base-namespace)) (eval '(需要方案) ns)

(定义框架 (new frame%[label "Simple Editor"] [width 800] [height 200])) (定义文本编辑器 (新球拍:文本%)) (定义画布 (new editor-canvas% [parent frame] (min-height 120)[editor text-editor]))

(发送帧显示#true)

(定义文本编辑器2 (新球拍:文本%)) (定义画布2 (new editor-canvas% [parent frame] (min-height 120)[editor text-editor2]))

(define hpa (new Horizo​​ntal-panel% (父框架)(alignment '(center center))))

(定义 BUTTON-EVAL (新按钮% (父 hpa) (标签“评估者”) (样式'(边框)) (回调 (lambda (b e) ; b=button, e=event (发送 text-editor2 擦除) (let ((L (read-from-string-all (send text-editor get-text)))) (for-each (lambda (expr) (发送 text-editor2 插入 (expr->string (eval expr ns))) (发送文本编辑器 2 插入“\n”)) L))))))

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多