Is it possible to detect esc key with ask function?
Would开发者_开发问答 like to detect esc key to escape the forever loop in pseudo code:
forever [ url: ask "Url: " if (url = esc) [ break ] ]
Is this possible ?
There is no simple answer, you must use own console-port to handle it correctly, here is the part of it taken from one of my old projects:
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
]
]
You will probably like to change the ctx-console/on-escape and ctx-console/on-enter functions.
As a pure console application, I'm pretty sure the answer is no.
esc is used to cancel the execution of the script.
You can disable that use of esc....
system/console/break: false
....And the esc key now does nothing.
If you switch to REBOL/VIEW and are happy to use a pop up request-text box rather than a console ask line, then you may be able to trap esc using insert-event-func.
精彩评论