So far, information has only gone one way: from your program to the screen. To write a program the user can actually interact with, information needs to come back the other way too.
In an ordinary terminal, whatever the user types is sent straight to your program. The ioL console works differently: nothing is sent to your program unless your output says so. That gives you complete control over what input your program receives, and when.
The putLn tag sends a line of input to your program. Your program reads it just
as it would read a line the user typed in a terminal: in Python, with input().
print('<putLn {Hello from the console}>')
line = input()
print('My program received: ' + line)
input()
My program received: Hello from the console
Here the console sends the line as soon as it reads the tag. That's not very useful by itself: the program already knew what it said! It gets interesting when the tag only runs when the user does something.
A few details:
input() the line is complete. Its partner, put, sends exactly what you
give it, with no newline.<putLn {score: }, 42> sends score: 42.<putLn> on its own sends a blank line.A button tag puts a button on the screen. Its primary field holds whatever appears on the button's face:
<button {Click me}>
To make the button do something, give it an onClick field. This is a new kind of field. Instead of holding a value, it holds code: tags that aren't carried out straight away, but are kept and carried out each time the user clicks the button. Clicking is an event, and fields that hold code for events are called code fields.
print('<button {Click me} onClick=<putLn {clicked}>></n>')
while True:
line = input()
print('The button was ' + line + '! </n>')
Each click sends the line clicked to the program, which prints a message in reply:
Notice the shape of this program. It sets up its interface, then sits in a loop waiting for input and responding to it. Most ioL programs look like this.
A code field can hold a list of tags, separated by commas. They're carried out in order:
<button {Go} onClick=<putLn {first}>, <putLn {second}>>
An input tag gives the user a box to type in. To send what they've typed to your program, the button that submits it needs a way to refer to the input box. So you give the input box a name, by writing a name and a colon in front of the tag type:
<name:input>
Now name stands for whatever is typed in that box. (You'll learn much more about names in the next chapter.) Here's a complete program:
print('''
What's your name?</n>
<name:input>
<button {OK} onClick=<putLn name>, name.clear>
<button {Quit} onClick=<putLn {/quit}>>
</p>
''')
while True:
line = input()
if line == '/quit':
break
print('Hello, ' + line + '!</n>')
What's your name?When the user clicks OK, two things happen. First, <putLn name> sends the typed
text to the program. Then name.clear empties the box, ready for the next name.
Look at the Quit button. It sends the line /quit, and when the program receives it, the
program leaves its loop and finishes. Because the program ends normally, the ioL console closes too.
This is the proper way to let the user end your program, and you no longer need an
input() at the end just to keep the window open.
Why /quit and not just quit? Because the program can't tell where a line came from. If the user typed quit as their name, the program would end. Choose commands that real input is unlikely to contain. (Can you do better than "unlikely"? There's a challenge at the end of this chapter.)
It's worth pausing on how this differs from a terminal program. A terminal program asks a question, then waits for the answer to that question. In ioL, your program sets up a screen full of things the user can do, in any order, and then waits for whatever happens next. Each line of input needs to say what happened. That's why it's common to send short commands, like /quit, and have your program check which one it received.
import random
secret = random.randint(1, 100)
tries = 0
print('''
<console.title {Guess the Number}>
<span size=18,pt bold=true {Guess the Number}></p>
I'm thinking of a number from 1 to 100.</n>
<guess:input>
<button {Guess} onClick=<putLn guess>, guess.clear>
<button {Give up} onClick=<putLn {/quit}>>
</p>
''')
while True:
line = input()
if line == '/quit':
break
if not line.isdigit():
print('<span color={orange} {Please type a whole number.}></n>')
continue
tries += 1
number = int(line)
if number < secret:
print(line + ' is too low.</n>')
elif number > secret:
print(line + ' is too high.</n>')
else:
print('<span bold=true color={lime} {' + line + ' is right! You took '
+ str(tries) + ' tries.}></n>')
Guess the NumberBe careful when you put text from the user into your output, as this program does with line. Here it's safe, because the program checks the guess is a number first. But if a user typed < or { into a name box, and your program printed it back unchanged, the console would read it as markup. You'll see how to deal with this safely later.