You can receive user input while your program is running by
scanning #process-input
. #process-input
represents standard input, which, by default, is
the keyboard. In order to receive the user's input as it is typed, you must turn off the buffering that OmniMark
performs on #process-input
. You do this with the declaration declare #process-input has
unbuffered
.
To prompt the user, you output a prompt and then scan #process-input
, as in the following
program. Note that you can scan #process-input
as many times as you need to:
declare #process-input has unbuffered process using output as file "rhyme.txt" submit "Mary had a little lamb." find ("big" | "little") => current-size put #log "The current size is %"" || current-size || "%"%n" || "Enter the correct size: " do scan #process-input match any-text* => correct-size "%n" output correct-size done find ("Mary" | "Tom") => current-owner put #log "The current lamb owner is %"" || current-owner || "%"%n" || "Enter the correct owner: " do scan #process-input match any-text* => correct-owner "%n" output correct-owner done find any => character output character
This program will create the file rhyme.txt
with the revised version of the input rhyme. In this
program, the prompt was sent to #log
to avoid interrupting the flow of data to the current output, which is
the the file rhyme.txt
. #log
is useful for prompting because it is not buffered, meaning that
the prompt is sent directly to the screen without delay.
If you need to prompt the user repeatedly, you can create a function to prompt for user input:
define string function get-user-input (value string prompt) as put #log prompt do scan #process-input match any-text* => user-input "%n" return user-input done
You can also carry on a conversation with the user in a single scan. Here is a program that implements a simple
calculator. The program evaluates each expression that the user enters and outputs the answer. Because there is no
other output going on, the program uses simple output
actions to prompt the user. To make this
work, #process-output
must be declared unbuffered
as well as #process-input
:
import "ombcd.xmd" unprefixed declare #process-input has unbuffered declare #process-output has unbuffered constant string prompt initial {"%ncalc> "} define switch function valid-number () as return #current-input matches (["+-"]? digit+ ("." digit+)?) process output prompt submit #process-input find valid-number () => left ["+-*/"] => operator valid-number () => right "%n" do scan operator match "+" output "d" % (bcd left + bcd right) match "-" output "d" % (bcd left - bcd right) match "*" output "d" % (bcd left * bcd right) match "/" output "d" % (bcd left / bcd right) done catch #program-error output "Invalid operation." always output prompt find ul ("exit" | "bye" | "quit") "%n" halt find any-text* "%n" output "Invalid input." || prompt
Note that this technique for getting user input will not work if your OmniMark program is called by another
process which binds standard input. In this case, #process-input
will represent data passed from the calling
process and not the input from the keyboard.