Use of and codes

In we will:

 Note  Each Lesson relies on your files from the previous one. It's better to use your own files, but if you can't, download a copy of files as they were at the end of Lesson 2 and click instructions. Remember you can if you prefer.

Creating a menu of choices in a script

More than any other feature, what distinguishes a good script from a mediocre one is a menu to allow the person using it to control what the script does. Once you know how to create menus, you'll probably use them in most of your scripts.

In summary, the process is:

We know how to display text with , so let's look at the next steps. To specify a list of reply keys (and get one in reply from the user), we need the command: .

By default, has two replies,  Y  and  N 

You list the reply keys you decide to accept in a switch on the command-line. The command will wait for a reply, and return an that tells your script what it was. If a key is pressed that is not on the list, beeps, and simply waits for one that is on the list.

The default list built into English language versions of the command is yn, and to reply you must press either:

By default replies are case-insensitive

You can make case-sensitive to replies, but by default, it isn't (which is usually more convenient). Let's try using choice with its default replies :

The command waits for a reply from its list

The command displays the list of acceptable replies, a  ? , then waits for your reply. The reply accepted is then displayed in uppercase (whether or not you typed it in uppercase), unless you add the /s case-sensitive switch (explained later).

Now reply with an  N  :

Wrong reply is beeped

Now try an unsuitable response; try the keys  Q   A   B  in turn :

Abort with  Ctrl C 

The command waits for a suitable response. You can abort the command by pressing  Ctrl C  (hold down  Ctrl  and press  C ). Try this now :

Use a Return-code shell to see what's happening

In those Exercises, has been returning a code for the key we pressed. We'll work in a Return-code shell and see what has been happening. Open a Return-code child shell in the  BatchWindow  now with our script RC.BAT :

The prompt change is a reminder

The script changes the prompt in the Return-code shell for us (purely as a convenient reminder). Remember, the original prompt will be restored automatically when we the Return-code shell.

The reply is returned as an

The command returns an code that is simply the reply key's position in the list.

In a script you would test for the code returned, then act accordingly. In our Return-code shell, we'll see the code displayed. Try the  Y  and  N  replies again :

Reply  Y  is first in the list

Since  Y  is the first reply key in the default list, an of 1 is returned to show it was pressed. Now try an  N  response :

A Return-code shell makes codes visible

Now we can see the effect of giving different replies from the list. Working in a Return-code shell is a good idea when developing scripts for any commands that pass information via codes.

Setting the reply list with the /c switch

We can set our own list of acceptable reply keys. Simply add the list to the command line prefixed with /c: (the  :  isn't strictly necessary, but it makes the list stand out more clearly from the switch letter). By the way, don't leave a  Space  in the list. If you do, the items in the list after the  Space  won't be used properly.

Suppose we want the user to choose from the three replies  Q ,  A  and  B . We specify the list of acceptable replies like this:

choice /c:qab

Of course, a script would have commands (before this line) to tell the user what these replies mean, that is, what actions they'll result in. We won't worry about that for now (except to observe that a  Q  for Quit option is useful on most menus).

Each reply returns a different code

Try it now. Type the command three times, replying with each of the keys  Q ,  A , and  B  in turn :

A /c reply list overrides the usual defaults

Check that it won't work with other keys. Try with the same reply list, but this time answer with  Y , and then  N  :

Aborting with  Ctrl C  gives zero return code

Abort the command with  Ctrl C  :

When is aborted by  Ctrl C  it returns code 0 (zero). In this case a zero means that something went wrong – the user aborted the command.

If there's an error, you receive code 255

As we saw in Lesson 2, if there's an error in the command-line syntax, such as choice /x (an invalid switch), the line returns 255 :

The code is the position of the reply in the list

As we said, the rule for values returned is: when a key in your list is pressed, simply returns the position of it in your /c: reply list. We've already seen that

choice /c:qab

This rule is very easy to remember. If you put the same key twice in the list, returns the code corresponding to the first position the key occurs :

The /s case-sensitive switch

However, you can mix uppercase and lowercase letters if you specify that should be case-sensitive to replies by using the /s switch. Try this :

The case-sensitive switch isn't often used

When you replied lowercase  a , returned position 2. But when you replied uppercase  A  it returned position 4. The /s case-sensitive switch is not often used. We'll use some other switches later in the Course.

testing:
In a script you must test for the code returned

 
We've seen that working in a Return-code shell makes it easy to see what's happening with commands that pass information in this way. Working this way is purely so that we can see the results during developing and testing. The final script will run in a normal shell. Our script will have to test for the returned when the user makes a selection from its menu.

The test uses

We use the command for this purpose, and the format of the test is:

IF ERRORLEVEL n   (followed by a command to be executed if the test is true)

The n is the value you test for. The command you add must be on the same line. We'll use an command, so that we see a message whenever the test is true. When the test is false, the command attached to it is not executed.

The test is for greater-than-or-equal-to

We know the return code can take any value from 0 to 255 (inclusive), and you can test for any number, n, in this range. But, and this is an important "but":

The test is true if the current is greater than or equal to the value n that you test for. It's a common mistake to assume the test is for strict equality. It is not, it's a test for greater than or equal to. We'll remind ourselves of this potential pitfall incessantly. Let's get some practice.

Test for greater-than-or-equal-to 4

We know that the current in the  BatchWindow  is 4, so let's just try out the test now. We'll test for a value of 4 :

The test is true, the current level is greater than or equal to 4 (since it's equal to 4), so the command was executed.

Test for greater-than-or-equal-to 5

Now test for a value of 5. Remember the test will ask if the current value is greater-than-or-equal-to 5. We know it's not, so this test will fail :

This time, the test is false, the current level is not greater than or equal to 5 (since we know it's still 4), so the command is not executed.

Test for a value below current

The test is true whenever we test for a value less than the current . Test for a value of 3 to confirm this :

The test is for greater-than-or-equal-to

The test is true, the current level is greater than or equal to 3 (it's still 4), so the command is executed. Of course, the message echoed is not true, but that's our fault: we should have worded our command line to read something like:

if errorlevel 3 echo.it is greater than or equal to 3

Each of the other messages (in and ) should have been worded in this cautious way to be strictly true whenever they are displayed.

The test is always for greater-than-or-equal-to

We can't emphasize it enough — whenever you use a test like:

you must always remember to think of it as the full version:

Asking a question:
A script with a menu

 
Let's write a simple script with a menu – well, it's really just a single question with lots of possible answers, but technically, it's a menu. Start Notepad from the command line, as usual. We'll call the new script MENU.BAT :

Ask a question and get an answer

We'll a question, then use to get an answer. Type the script. Make sure you press  Return  at the end of the last line to terminate it properly :

Test the script

No letters missed from the alphabet?  Return  pressed after the last line? And File, Save clicked? Let's test what we have so far. Run it, and answer  K  :

Add test

Well, Windows got the return code right –  K  definitely is the 11th letter of the alphabet even if it's not the right answer! By the way, remember, it's only while we're in a Return-code shell we can actually see the return codes for the answers displayed like this.

The right answer =  J  which would return 10

We know that the answer is  J  (for Jean), and that  K  is wrong. But our script doesn't. We need to code some tests for whether or not an answer is right.

Designing efficient tests

Let's try an assortment of answers, some always later in the alphabet than the right answer, and others always earlier than the right answer. Then the best way to design the right tests will gradually become clearer.

If we press  L , which is also wrong, we'll get code 12 returned. And the rest of the alphabet, all the way to  Z  (which would give 26), would be wrong, too :

Ruling out the 11th and all following letters

All the letters from  K  to  Z  will return codes greater than or equal to 11. We can handle them with one test: IF ERRORLEVEL 11 since greater than or equal to 11 is exactly what it is testing for.

Let's use that test to display a message that the answer is wrong :

Check the script again

You remembered the  Return  at the end, and to click File, Save? Let's check the script. Run it and answer  K  :

Check with  Z 

Check that the script knows  Z  is wrong now :

More wrong answers

Run the script again, and this time answer  I  :

Codes for  I  to  A  are below the right answer

If we press  H , which is also wrong, we'll get code 8 returned. And the rest of the alphabet, back to  A  (which would give 1), would be wrong, too :

The IF NOT test

Replies from  A  = 1 to  I  = 9 give codes that are NOT greater than or equal to 10. We can handle them with the other version of the test – IF NOT.

IF NOT ERRORLEVEL 10 is true for all return code values strictly less than 10. Let's add that test. Again, we'll use it to say the answer is wrong :

Remember: –   IF NOT ERRORLEVEL 10
means: – if the code returned is NOT greater than or equal to 10

Use a wrong answer that's too low

We've clicked File, Save, so check the script again. This time we'll reply with a letter that we know is too low in the alphabetical reply list. Try  D  :

What if we're right?

Our script has nothing to deal with a right answer yet. Try it out :

We ruled out answers from  K  to  Z  with one test for 11. And we ruled out answers from  A  to  I  with one IF NOT test for 10.

No exact equality test

Unfortunately, there isn't an IF exactly equal test – which would be useful here. However, we can combine two tests in one line.

If we start with a test IF NOT ERRORLEVEL 11, that test is true for all the reply letters NOT greater than or equal to the 11th – in other words, those from  A  to  J .

Combining two tests

Any command we add on to that is executed only if the reply is  A  to  J . If we add a test that's only true for  J  to  Z , then only the reply  J  would satisfy both tests. Since  J  is the 10th letter, we need to add IF ERRORLEVEL 10:

IF NOT ERRORLEVEL 11 IF ERRORLEVEL 10  true only for =10

This is what we need. Add that combination, with a suitable message :

It would work the other way round, too

The combination also works the other way around, since only  J =10 passes both tests:

IF ERRORLEVEL 10 IF NOT ERRORLEVEL 11  true only for =10

Test the script

You remembered to press  Return  at the end of the line, and to click File, Save? Run the script again, this time answer  J  :

Suppress option list

We'll add one final touch. With this use of , we don't really need to see the whole alphabet listed on screen each time. You can suppress the display of the reply list with the /n switch. Add this to the command line in the script :

Close Return-code shell

Let's exit the Return-code shell before we test the script :

Try a letter that's too low

We clicked File, Save so run MENU.BAT again, and answer  I  :

Try one that's too high

Now try replying  K  :

Get the answer right

And finally – get it right! :

Now, along with the young man in the 22nd row , we'll say Goodbye Norma Jean.

In Candle in the Wind (Elton John on Phonogram CD 846949-2), the lyricist Bernie Taupin wrote (of Marilyn Monroe):
"Goodbye Norma Jean,
Though I never knew you at all.
You had the grace to hold yourself,
While those around you crawled.
Goodbye Norma Jean,
From the young man in the 22nd row..."

What we have learnt

In this Lesson we have learnt how to:

The /? help for commands doesn't list the s they return, but (when you're on-line) you can get our list (click and use the link).

The Index has the Syllabus for the next Lesson, where we'll write another script to work with s. See you then.

© Copyright 2003- Allen & Company. All rights reserved ©