【问题标题】:Is it possible to detect esc key with ask function?是否可以使用询问功能检测 esc 键?
【发布时间】:2025-12-06 09:20:03
【问题描述】:

想检测 esc 键以逃避伪代码中的永远循环:

永远[ 网址:问“网址:” 如果(网址=esc)[ 休息 ] ]

这可能吗?

【问题讨论】:

    标签: rebol esc-key


    【解决方案1】:

    没有简单的答案,你必须使用自己的控制台端口来正确处理它,这是从我的一个旧项目中摘录的部分:

    REBOL [title: "Console port"]
    
    set 'ctx-console make object! [
        system/console/busy: none
        system/console/break: false
        buffer: make string! 512
        history: system/console/history
        prompt: "## " ;system/console/prompt
        spec-char: none
        port: none
        init: func[][
            port: open/binary [scheme: 'console]
            set 's-print get in system/words 'print
            set 's-prin  get in system/words 'prin
            set 'prin func[msg /err /inf /user user-data][
                ctx-console/clear-line
                s-prin reform msg
                ctx-console/print-line
            ]
            set 'print func[msg /err /inf /user user-data][
                prin rejoin [reform msg newline]
            ]
            s-prin prompt
        ]
        print-line: func[][
            s-prin rejoin [ prompt head buffer "^(1B)[" length? buffer "D"]
        ]
        clear-line: func[][
            s-prin rejoin [
                "^(1B)[" (
                (index? buffer) +
                (length? prompt) +
                (length? buffer))
                "D^(1B)[K"
            ]
        ]
        key-actions: make block! [
            #{08} [;BACK
                if 0 < length? head buffer [
                    buffer: remove back buffer
                    s-prin rejoin [
                        "^(back)^(1B)[K"
                        buffer
                        "^(1B)["
                        length? buffer "D"
                    ]
                ]
            ]
            #{7E} [;HOME
                s-prin rejoin ["^(1B)[" (index? buffer) - 1 "D"]
                buffer: head buffer
            ]
            #{7F} [;DELETE
                buffer: remove buffer
                s-prin rejoin ["^(1B)[K" buffer "^(1B)[" length? buffer "D"]
            ]
            #{1B} [;ESCAPE
                spec-char: copy/part port 1
                either spec-char = #{1B} [
                    print "ESCAPE"
                    clear-line
                    set 'print :s-print
                    set 'prin  :s-prin
                    system/console/break: true
                    on-escape
                ][
                    switch append spec-char copy/part port 1 [
                        #{5B41} [;ARROW UP
                            if not tail? history [
                                clear-line
                                clear head buffer
                                s-prin join prompt buffer: copy history/1
                                history: next history
                                buffer: tail buffer
                            ]
                        ]
                        #{5B42} [;ARROW DOWN
                            clear-line
                            buffer: head buffer
                            clear buffer
                            if all [
                                not error? try [history: back history]
                                not none? history/1
                            ] [
                                buffer: copy history/1
                            ]
                            s-prin join prompt buffer
                            buffer: tail buffer
                        ]
                        #{5B43} [;ARROW RIGHT
                            if not tail? buffer [
                                s-prin "^(1B)[C"
                                buffer: next buffer
                            ]
                        ]
                        #{5B44} [;ARROW LEFT
                            if 1 < index? buffer [
                                s-prin "^(1B)[D"
                                buffer: back buffer
                            ]
                        ]
                    ]
                ]
            ]
        ]
        do-command: func[comm /local e][
            set/any 'e attempt compose [do (comm)]
    
            if all [
                not unset? 'e
                value? 'e
                not object? :e
                not port? :e
                not function? :e
            ][
                print head clear skip rejoin [system/console/result mold :e] 127
                if (length? mold :e) > 127 [
                    print "...^/"
                ]
            ]
        ]
        on-enter: func[input-str /local e][
            print rejoin [system/console/prompt input-str]
            do-command input-str
        ]
        on-escape: func[][halt]
        process: func[/local ch c tmp spec-char err][
            ch: to-char pick port 1
            either (ch = newline) or (ch = #"^M") [;ENTER
                tmp: copy head buffer
                if empty? tmp [return none]
                history: head history
                if any [empty? history tmp <> first history ] [
                    insert history tmp
                ]
                clear-line
                buffer: head buffer
                clear buffer
                print-line
                on-enter tmp
            ][
                switch/default to-binary ch key-actions [
                    either tail? buffer [
                        s-prin ch ;either local-echo [ch]["*"]
                    ][
                        s-prin rejoin ["^(1B)[@" ch]
                    ]
                    buffer: insert buffer ch
                ]
            ]
        ]
    ]
    ctx-console/init
    
    ;and now do something with your own console:
    wait-list: reduce [ctx-console/port]
    forever [
        attempt [ready: wait/all wait-list]
        if ready [
            ctx-console/process
        ]
    ]
    

    您可能希望更改 ctx-console/on-escapectx-console/on-enter 功能。

    【讨论】:

    • 非常感谢,看起来很棒会尝试但我不是rebol大师,可惜Rebol控制台不能轻松定制,虽然Rebol控制台很棒,但我希望它可以更大:)
    • 如果您知道控制台的存在,定制控制台并不难。请注意,此代码作为示例可能过于复杂,因为它用于控制台中的 irc-client,因此能够打印消息并且仍然具有可用输入而不丢失其内容非常重要。
    • 顺便说一句.. 我期待在 R3 中有更好的控制台 - 支持 unicode 和富文本 :)
    【解决方案2】:

    作为一个纯粹的控制台应用程序,我很确定答案是

    esc用于取消脚本的执行。

    您可以禁用 esc....

     system/console/break: false
    

    ....esc 键现在什么都不做。

    如果您切换到 REBOL/VIEW 并乐于使用弹出 request-text 框而不是控制台 ask 行,那么你也许可以使用 insert-event-func 来捕获 esc

    【讨论】:

    最近更新 更多