Menu

From Rosetta Code
Revision as of 01:21, 18 February 2011 by Peter (talk | contribs) (added Fantom example)
Task
Menu
You are encouraged to solve this task according to the task description, using any language you may know.

Given a list containing a number of strings of which one is to be selected and a prompt string, create a function that:

  • Print a textual menu formatted as an index value followed by its corresponding string for each item in the list.
  • Prompt the user to enter a number.
  • Return the string corresponding to the index number.

The function should reject input that is not an integer or is an out of range integer index by recreating the whole menu before asking again for a number. The function should return an empty string if called with an empty list.

For test purposes use the four phrases: “fee fie”, “huff and puff”, “mirror mirror” and “tick tock” in a list.

Note: This task is fashioned after the action of the Bash select statement.

Ada

<lang Ada> -- menu2.adb -- -- rosetta.org menu example -- GPS 4.3-5 (Debian)

-- note: the use of Unbounded strings is somewhat overkill, except that -- it allows Ada to handle variable length string data easily -- ie: differing length menu items text with Ada.Text_IO, Ada.Integer_Text_IO, Ada.Strings.Unbounded,

    Ada.Strings.Unbounded.Text_IO;

use Ada.Text_IO, Ada.Integer_Text_IO,

   Ada.Strings.Unbounded, Ada.Strings.Unbounded.Text_IO;

procedure menu2 is

package tio  renames Ada.Integer_Text_IO;
 -- rename package to use a shorter name, tio, as integer get prefix
menu_item : array (1..4) of Unbounded_String;
               -- 4 menu items of any length
choice    : integer := 0;
                -- user selection entry value
  procedure show_menu is

-- display the menu options and collect the users input -- into locally global variable 'choice'

  begin
      for pntr in menu_item'first .. menu_item'last  loop
         put (pntr ); put(" "); put( menu_item(pntr)); new_line;
      end loop;
      put("chose (0 to exit) #:"); tio.get(choice);
  end show_menu;

-- main program -- begin

menu_item(1) := to_unbounded_string("Fee Fie");
menu_item(2) := to_unbounded_string("Huff & Puff");
menu_item(3) := to_unbounded_string("mirror mirror");
menu_item(4) := to_unbounded_string("tick tock");
        -- setup menu selection strings in an array
show_menu;
loop
  if choice in menu_item'range then
    put("you chose #:");
    case choice is
     -- in a real menu, each case would execute appropriate user procedures
 	when 1 => put ( menu_item(choice)); new_line;
       when 2 => put ( menu_item(choice)); new_line;
       when 3 => put ( menu_item(choice)); new_line;
       when 4 => put ( menu_item(choice)); new_line;
       when others => null;
    end case;
 	show_menu;
  else
   	put("Menu selection out of range"); new_line;
   	if choice = 0 then exit; end if;
           -- need a exit option !
   	show_menu;
  end if;
end loop;

end menu2;

</lang>

<lang Ada> ./menu2

         1 Fee Fie
         2 Huff & Puff
         3 mirror mirror
         4 tick tock

chose (0 to exit) #:2 you chose #:Huff & Puff

         1 Fee Fie
         2 Huff & Puff
         3 mirror mirror
         4 tick tock

chose (0 to exit) #:55 Menu selection out of range

         1 Fee Fie
         2 Huff & Puff
         3 mirror mirror
         4 tick tock

chose (0 to exit) #:0 Menu selection out of range [2010-06-09 22:18:25] process terminated successfully (elapsed time: 15.27s)

</lang>

ALGOL 68

Translation of: C
Works with: ALGOL 68 version Revision 1 - no extensions to language used
Works with: ALGOL 68G version Any - tested with release 1.18.0-9h.tiny

<lang algol68>PROC menu select := (FLEX[]STRING items, UNION(STRING, VOID) prompt)STRING: (

       INT choice;
      
       IF LWB items <= UPB items THEN
               WHILE
                       FOR i FROM LWB items TO UPB items DO
                               printf(($g(0)") "gl$, i, items[i]))
                       OD;
                       CASE prompt IN
                               (STRING prompt):printf(($g" "$, prompt)),
                               (VOID):printf($"Choice ? "$)
                       ESAC;
                       read((choice, new line));
               # WHILE # 1 > choice OR choice > UPB items
               DO SKIP OD;
               items[choice]
       ELSE
               ""
       FI

);

test:(

       FLEX[0]STRING items := ("fee fie", "huff and puff", "mirror mirror", "tick tock");
       STRING prompt := "Which is from the three pigs : ";
       printf(($"You chose "g"."l$, menu select(items, prompt)))

)</lang> Output:

1) fee fie
2) huff and puff
3) mirror mirror
4) tick tock
Which is from the three pigs :  2
You chose huff and puff.

AutoHotkey

<lang autohotkey>GoSub, CreateGUI return

Submit: Gui, Submit, NoHide If Input =

GuiControl,,Output

Else If Input not between 1 and 4 {

Gui, Destroy
Sleep, 500
GoSub, CreateGUI

} Else {

GuiControlGet, string,,Text%Input%
GuiControl,,Output,% SubStr(string,4)

} return

CreateGUI: list = fee fie,huff and puff,mirror mirror,tick tock Loop, Parse, list, `,

Gui, Add, Text, vText%A_Index%, %A_Index%: %A_LoopField%

Gui, Add, Text, ym, Which is from the three pigs? Gui, Add, Edit, vInput gSubmit Gui, Add, Edit, vOutput Gui, Show return

GuiClose: ExitApp</lang>

BASIC

Works with: QuickBasic version 4.5

<lang qbasic> function sel$(choices$(), prompt$)

  if ubound(choices$) - lbound(choices$) = 0 then sel$ = ""
  ret$ = ""
  do
     for i = lbound(choices$) to ubound(choices$)
        print i; ": "; choices$(i)
     next i
     input ;prompt$, index
     if index <= ubound(choices$) and index >= lbound(choices$) then ret$ = choices$(index)
  while ret$ = ""
  sel$ = ret$

end function</lang>

Brat

<lang brat>menu = { prompt, choices |

 true? choices.empty?
 { "" }
 {
   choices.each_with_index { c, i |
     p "#{i}. #{c}"
   }
   selection = ask prompt
     true? selection.numeric?
     { selection = selection.to_i
       true? selection < 0 || { selection >= choices.length }
         { p "Selection is out of range"; menu prompt, choices }
         { choices[selection] }
     }
   { p "Selection must be a number"; menu prompt, choices }
 }

}

p menu "Selection: " ["fee fie" "huff and puff" "mirror mirror" "tick tock"]</lang>

C

<lang c>#include <stdio.h>

  1. include <stdlib.h>
  2. include <string.h>

char *menu_select(char **items, char *prompt);

int main(void) { char *items[] = {"fee fie", "huff and puff", "mirror mirror", "tick tock", NULL}; char *prompt = "Which is from the three pigs?";

printf("You chose %s.\n", menu_select(items, prompt));

return EXIT_SUCCESS; }

char * menu_select(char **items, char *prompt) { char buf[BUFSIZ]; int i; int choice; int choice_max;

if (items == NULL) return NULL;

do { for (i = 0; items[i] != NULL; i++) { printf("%d) %s\n", i + 1, items[i]); } choice_max = i; if (prompt != NULL) printf("%s ", prompt); else printf("Choice? "); if (fgets(buf, sizeof(buf), stdin) != NULL) { choice = atoi(buf); } } while (1 > choice || choice > choice_max);

return items[choice - 1]; }</lang>

C++

<lang cpp>#include <iostream>

  1. include <boost/regex.hpp>
  2. include <cstdlib>
  3. include <string>

using namespace std;

void printMenu(const string *, int); //checks whether entered data is in required range bool checkEntry(string, const string *, int);

string dataEntry(string prompt, const string *terms, int size) {

  if (size == 0) { //we return an empty string when we call the function with an empty list
     return "";
  }
  
  string entry;
  do {
     printMenu(terms, size);
     cout << prompt;

     cin >> entry;
  }
  while( !checkEntry(entry, terms, size) );

  int number = atoi(entry.c_str());
  return terms[number - 1];

}

void printMenu(const string *terms, int num) {

  for (int i = 1 ; i < num + 1 ; i++) {
     cout << i << ')' << terms[ i - 1 ] << '\n';
  }

}

bool checkEntry(string myEntry, const string *terms, int num) {

  boost::regex e("^\\d+$");
  if (!boost::regex_match(myEntry, e)) 
     return false;
  int number = atoi(myEntry.c_str());
  if (number < 1 || number > num) 
     return false;
  return true;

}

int main( ) {

  const string terms[ ] = { "fee fie" , "huff and puff" , "mirror mirror" , "tick tock" };
  int size = sizeof terms / sizeof *terms;
  cout << "You chose: " << dataEntry("Which is from the three pigs: ", terms, size);
  return 0;

}</lang>

C#

<lang csharp>

       static void Main(string[] args)
       {
           List<string> menu_items = new List<string>() { "fee fie", "huff and puff", "mirror mirror", "tick tock" };
           //List<string> menu_items = new List<string>();
           Console.WriteLine(PrintMenu(menu_items));
           Console.ReadLine();
       }
       private static string PrintMenu(List<string> items)
       {
           if (items.Count == 0)
               return "";
           string input = "";
           int i = -1;
           do
           {
               for (int j = 0; j < items.Count; j++)
                   Console.WriteLine("{0}) {1}", j, items[j]);
               Console.WriteLine("What number?");
               input = Console.ReadLine();
           } while (!int.TryParse(input, out i) || i >= items.Count || i < 0);
           return items[i];
       }

</lang>

Clojure

<lang clojure>(defn menu [prompt choices]

 (if (empty? choices) 
   ""
   (let [menutxt (apply str (interleave
                             (iterate inc 1)
                             (map #(str \space % \newline) choices)))]
     (println menutxt)
     (print prompt)
     (flush)
     (let [index (read-string (read-line))]
       ; verify
       (if (or (not (integer? index))
               (> index (count choices))
               (< index 1))
         ; try again
         (recur prompt choices)
         ; ok
         (nth choices (dec index)))))))

(println "You chose: "

        (menu "Which is from the three pigs: "
              ["fee fie" "huff and puff" "mirror mirror" "tick tock"]))</lang>

Common Lisp

<lang lisp>(defun select (prompt choices)

 (if (null choices)
   ""
   (do (n)
       ((and n (<= 0 n (1- (length choices))))
        (nth n choices))
     (format t "~&~a~%" prompt)
     (loop for n from 0
           for c in choices
           do (format t "  ~d) ~a~%" n c))
     (force-output)
     (setf n (parse-integer (read-line *standard-input* nil)
                            :junk-allowed t)))))</lang>

D

<lang d>import std.stdio; import std.conv; import std.string; void main() {

       char[][]items = ["fee fie","huff and puff","mirror mirror","tick tock"];
       writefln("You chose %s",doSelect(items));

}

char[]doSelect(char[][]input) {

       if (!input.length) return "";
       char[]line;
       int choice;
       do {
               writefln("Choose one:");
               foreach(i,item;input) {
                       writefln("%d) %s",i,item);
               }
               writef("> ");
               line = readln();
               line = chomp(line);
               choice = ValidChoice(input.length-1,line);
       } while (choice == -1);
       // we have a valid choice
       return input[choice];

}

int ValidChoice(int max,char[]input) {

       int tmp;
       try tmp = toInt(input);
       catch(Error e) return -1;
       if (tmp <= max && tmp >= 0) {
               return tmp;
       }
       return -1;

}</lang>

Factor

<lang factor>USE: formatting

print-menu ( seq -- )
   [ 1 + swap "%d - %s\n" printf ] each-index
   "Your choice? " write flush ;
select ( seq -- result )
   dup print-menu
   readln string>number [
       1 - swap 2dup bounds-check?
       [ nth ] [ nip select ] if
   ] [ select ] if* ;</lang>

Example usage:

( scratchpad ) { "fee fie" "huff and puff" "mirror mirror" "tick tock" } select
1 - fee fie
2 - huff and puff
3 - mirror mirror
4 - tick tock
Your choice? 1

--- Data stack:
"fee fie"

Fantom

<lang fantom> class Main {

 static Void displayList (Str[] items)
 {
   items.each |Str item, Int index|
   {
     echo ("$index: $item")
   }
 }
 public static Str getChoice (Str[] items)
 {
   selection := -1
   while (selection == -1)
   {
     displayList (items)
     Env.cur.out.print ("Select: ").flush
     input := Int.fromStr(Env.cur.in.readLine, 10, false)
     if (input != null)
     {
       if (input >= 0 && input < items.size)
       {
         selection = input
       }
     }
     echo ("Try again")
   }
   return items[selection]
 }
 public static Void main ()
 {
   choice := getChoice (["fee fie", "huff and puff", "mirror mirror", "tick tock"])
   echo ("You chose: $choice")
 }

} </lang>

Haskell

<lang Haskell>module RosettaSelect where

import Data.Maybe (listToMaybe) import Control.Monad (guard)

select :: [String] -> IO String select [] = return "" select menu = do

 putStr $ showMenu menu
 putStr "Choose an item: "
 choice <- getLine
 maybe (select menu) return $ choose menu choice

showMenu :: [String] -> String showMenu menu = unlines [show n ++ ") " ++ item | (n, item) <- zip [1..] menu]

choose :: [String] -> String -> Maybe String choose menu choice = do

 n <- maybeRead choice
 guard $ n > 0
 listToMaybe $ drop (n-1) menu

maybeRead :: Read a => String -> Maybe a maybeRead = fmap fst . listToMaybe . filter (null . snd) . reads</lang>

Example usage, at the GHCI prompt: <lang Haskell>*RosettaSelect> select ["fee fie", "huff and puff", "mirror mirror", "tick tock"] 1) fee fie 2) huff and puff 3) mirror mirror 4) tick tock Choose an item: 3 "mirror mirror"

  • RosettaSelect></lang>

HicEst

<lang HicEst>CHARACTER list = "fee fie,huff and puff,mirror mirror,tick tock,", answer*20

  POP(Menu=list, SelTxt=answer)

SUBROUTINE list ! callback procedure must have same name as menu argument

! Subroutine with no arguments: all objects are global
! The global variable $$ returns the selected list index
  WRITE(Messagebox, Name) answer, $$

END</lang>

Icon and Unicon

<lang Icon>procedure main()

L := ["fee fie", "huff and puff", "mirror mirror", "tick tock"]

every i := 1 to *L do

  write(i,") ",L[i])

repeat {

  writes("Choose a number from the menu above: ")
  a := read()
  if 1 <= integer(a) <= i then break
  }

write("You selected ",a," ==> ",L[a]) end</lang>

J

Solution: <lang j>require'misc' showMenu =: i.@# smoutput@,&":&> ' '&,&.> makeMsg =: 'Choose a number 0..' , ': ',~ ":@<:@# errorMsg =: [ smoutput bind 'Please choose a valid number!'

select=: ({::~ _&".@prompt@(makeMsg [ showMenu)) :: ($:@errorMsg)</lang> See Talk page for explanation of code.

Example use: <lang j> select 'fee fie'; 'huff and puff'; 'mirror mirror'; 'tick tock'</lang>

This would display:

0 fee fie
1 huff and puff
2 mirror mirror
3 tick tock
choose a number 0..3:

And, if the user responded with 2, would return: mirror mirror

Java

<lang java5>public static String select(List<String> list, String prompt){

   if(list.size() == 0) return "";
   Scanner sc = new Scanner(System.in);
   String ret = null;
   do{
       for(int i=0;i<list.size();i++){
           System.out.println(i + ": "+list.get(i));
       }
       System.out.print(prompt);
       int index = sc.nextInt();
       if(index >= 0 && index < list.size()){
           ret = list.get(index);
       }
   }while(ret == null);
   return ret;

}</lang>

JavaScript

Works with: JScript

for the I/O.

<lang javascript>function select(question, choices) {

   var prompt = "";
   for (var i in choices) 
       prompt += i + ". " + choices[i] + "\n";
   prompt += question;
   var input;
   while (1) {
       WScript.Echo(prompt);
       input = parseInt( WScript.StdIn.readLine() );
       if (0 <= input && input < choices.length)
           break;
       WScript.Echo("\nTry again.");
   }
   return input;

}

var choices = ['fee fie', 'huff and puff', 'mirror mirror', 'tick tock']; var choice = select("Which is from the three pigs?", choices); WScript.Echo("you selected: " + choice + " -> " + choices[choice]);</lang>

Works with: UCB Logo

<lang logo>to select :prompt [:options]

 foreach :options [(print # ?)]
 forever [
   type :prompt type "| |
   make "n readword
   if (and [number? :n] [:n >= 1] [:n <= count :options]) [output item :n :options]
   print sentence [Must enter a number between 1 and] count :options
 ]

end

print equal? [huff and puff] (select

 [Which is from the three pigs?]
 [fee fie] [huff and puff] [mirror mirror] [tick tock])

</lang>

Lua

<lang lua>function choice(choices)

 for i, v in ipairs(choices) do print(i, v) end
 print"Enter your choice"
 local selection = io.read() + 0
 if choices[selection] then print(choices[selection])
 else choice(choices)
 end

end

choice{"fee fie", "huff and puff", "mirror mirror", "tick tock"}</lang>

MATLAB

<lang MATLAB>function sucess = menu(list)

   if numel(list) == 0
       sucess = ;
       return
   end
   while(true)
       
       disp('Please select one of these options:');
       
       for i = (1:numel(list))
       
           disp([num2str(i) ') ' list{i}]);
           
       end
       
       disp([num2str(numel(list)+1) ') exit']);
       
       try
           key = input(':: ');
           if key == numel(list)+1
               break
           elseif (key > numel(list)) || (key < 0)
               continue
           else
               disp(['-> ' list{key}]);
           end
       catch
           continue
       end
       
       
   end
   
   sucess = true;
   

end </lang>

MUMPS

<lang MUMPS>MENU(STRINGS,SEP)

;http://rosettacode.org/wiki/Menu
NEW I,A,MAX
;I is a loop variable
;A is the string read in from the user
;MAX is the number of substrings in the STRINGS list
;SET STRINGS="fee fie^huff and puff^mirror mirror^tick tock"
SET MAX=$LENGTH(STRINGS,SEP)
QUIT:MAX=0 ""

WRITEMENU

FOR I=1:1:MAX WRITE I,": ",$PIECE(STRINGS,SEP,I),!
READ:30 !,"Choose a string by its index: ",A,!
IF (A<1)!(A>MAX)!(A\1'=A) GOTO WRITEMENU
KILL I,MAX
QUIT $PIECE(STRINGS,SEP,A)</lang>

Usage:

USER>W !,$$MENU^ROSETTA("fee fie^huff and puff^mirror mirror^tick tock","^")
 
1: fee fie
2: huff and puff
3: mirror mirror
4: tick tock
 
Choose a string by its index: 3
mirror mirror
USER>W !,$$MENU^ROSETTA("fee fie^huff and puff^mirror mirror^tick tock","^")
 
1: fee fie
2: huff and puff
3: mirror mirror
4: tick tock
 
Choose a string by its index: 5
1: fee fie
2: huff and puff
3: mirror mirror
4: tick tock
 
Choose a string by its index: A
1: fee fie
2: huff and puff
3: mirror mirror
4: tick tock
 
Choose a string by its index: 0
1: fee fie
2: huff and puff
3: mirror mirror
4: tick tock
 
Choose a string by its index: 1
fee fie

OCaml

<lang ocaml>let rec select choices prompt = (* "choices" is an array of strings *)

 if Array.length choices = 0 then invalid_arg "no choices";
 Array.iteri (Printf.printf "%d: %s\n") choices;
 print_string prompt;
 let index = read_int () in
   if index >= 0 && index < Array.length choices then
     choices.(index)
   else
     select choices prompt</lang>

Oz

<lang oz>declare

 fun {Select Prompt Items}
    case Items of nil then ""
    else

for Item in Items Index in 1..{Length Items} do {System.showInfo Index#") "#Item} end {System.printInfo Prompt} try {Nth Items {ReadInt}} catch _ then {Select Prompt Items} end

    end
 end
 fun {ReadInt}
    class TextFile from Open.file Open.text end
    StdIo = {New TextFile init(name:stdin)}
 in
    {String.toInt {StdIo getS($)}}
 end
 
 Item = {Select "Which is from the three pigs: "

["fee fie" "huff and puff" "mirror mirror" "tick tock"]}

in

 {System.showInfo "You chose: "#Item}</lang>

Perl

<lang perl>sub menu {

       my ($prompt,@array) = @_;
       return  unless @array;
       print "  $_: $array[$_]\n" for(0..$#array);
       print $prompt;
       $n = <>;
       return $array[$n] if $n =~ /^\d+$/ and defined $array[$n];
       return &menu($prompt,@array);

}

@a = ('fee fie', 'huff and puff', 'mirror mirror', 'tick tock'); $prompt = 'Which is from the three pigs: ';

$a = &menu($prompt,@a);

print "You chose: $a\n";</lang>

PL/I

<lang PL/I> test: proc options (main);

declare menu(4) character(100) varying static initial (

  'fee fie', 'huff and puff', 'mirror mirror', 'tick tock');

declare (i, k) fixed binary;

do i = lbound(menu,1) to hbound(menu,1);

  put skip edit (trim(i), ': ', menu(i) ) (a);

end; put skip list ('please choose an item number'); get list (k); if k >= lbound(menu,1) & k <= hbound(menu,1) then

  put skip edit ('you chose ', menu(k)) (a);

else

  put skip list ('Could not find your phrase');

end test; </lang>

PicoLisp

<lang PicoLisp>(de choose (Prompt Items)

  (use N
     (loop
        (for (I . Item) Items
           (prinl I ": " Item) )
        (prin Prompt " ")
        (NIL (setq N (in NIL (read))))
        (T (>= (length Items) N 1) (get Items N)) ) ) )

(choose "Which is from the three pigs?"

  '("fee fie" "huff and puff" "mirror mirror" "tick tock") )</lang>

Output:

1: fee fie
2: huff and puff
3: mirror mirror
4: tick tock
Which is from the three pigs? 2
-> "huff and puff"

PureBasic

<lang PureBasic>If OpenConsole()

 Define i, txt$, choice
 Dim txts.s(4)
 EnableGraphicalConsole(1)  ;- Enable graphical mode in the console
 Repeat
   ClearConsole()
   Restore TheStrings       ; Set reads address
   For i=1 To 4
     Read.s  txt$
     txts(i)=txt$
     ConsoleLocate(3,i): Print(Str(i)+": "+txt$)
   Next
   ConsoleLocate(3,6): Print("Your choice? ")
   choice=Val(Input())
 Until choice>=1 And choice<=4
 ClearConsole()
 ConsoleLocate(3,2): Print("You chose: "+txts(choice))
 ;
 ;-Now, wait for the user before ending to allow a nice presentation
 ConsoleLocate(3,5): Print("Press ENTER to quit"): Input()

EndIf End

DataSection

 TheStrings:
 Data.s  "fee fie", "huff And puff", "mirror mirror", "tick tock"

EndDataSection</lang>

Python

<lang python>def _menu(items):

   for indexitem in enumerate(items):
       print ("  %2i) %s" % indexitem)

def _ok(reply, itemcount):

   try:
       n = int(reply)
       return 0 <= n < itemcount
   except:
       return False
   

def selector(items, prompt):

   'Prompt to select an item from the items'
   if not items: return 
   reply = -1
   itemcount = len(items)
   while not _ok(reply, itemcount):
       _menu(items)
       # Use input instead of raw_input for Python 3.x
       reply = raw_input(prompt).strip()
   return items[int(reply)]

if __name__ == '__main__':

   items = ['fee fie', 'huff and puff', 'mirror mirror', 'tick tock']
   item = selector(items, 'Which is from the three pigs: ')
   print ("You chose: " + item)</lang>

Sample runs:

   0) fee fie
   1) huff and puff
   2) mirror mirror
   3) tick tock
Which is from the three pigs:  -1
   0) fee fie
   1) huff and puff
   2) mirror mirror
   3) tick tock
Which is from the three pigs:      0
You chose: fee fie
>>> ================================ RESTART ================================
>>> 
   0) fee fie
   1) huff and puff
   2) mirror mirror
   3) tick tock
Which is from the three pigs: 4
   0) fee fie
   1) huff and puff
   2) mirror mirror
   3) tick tock
Which is from the three pigs: 3
You chose: tick tock

R

Uses menu. <lang R>showmenu <- function() {

  choices <- c("fee fie", "huff and puff", "mirror mirror", "tick tock")
  ans <- menu(choices)
  if(ans==0) "" else choices[ans]

} str <- showmenu()</lang>

REXX

<lang rexx> /*REXX program shows a list, asks user for a selection number (integer).*/

 do forever
 call list_create                     /*create the list from scratch.  */
 call list_show                       /*display (show) the list to user*/
 if list.0==0 then return           /*if empty list, then return null*/
 say 'choose an item by entering a number from  1 --->' list.0   /*ask.*/
 parse pull x                         /*get the user's choice (if any).*/
 ok=1                                 /*assume everything is peachy.   */
 if x=             then call sayErr "a choice wasn't entered"
 if words(x)\==1     then call sayErr 'too many choices entered:'
 if \datatype(x,'N') then call sayErr "the choice isn't numeric:"
 if \datatype(x,'W') then call sayErr "the choice isn't an integer:"
 if x<1 | x>list.0 then call sayErr "the choice isn't within range:"
 if ok then leave                     /*OK?  Then we got a good choice.*/
 end
                                      /*user might've entered 2. or 003*/

x=x/1 /*normalize the number (maybe). */ say; say 'you chose item' x": " list.x exit

list_create: /*there're other list-building methods.*/ list.1='fee fie' list.2='huff and puff' list.3='mirror mirror' list.4='tick tock' list.0=4 /*store # of choices in list.0 */ return /*(above) is just one convention.*/

list_show: say /*display a blank line. */

      do j=1 for list.0               /*display the list of choices.   */
      say '(item' j") " list.j        /*display item # with its choice.*/
      end

say /*display another blank line. */ return

sayErr: if \ok then return; ok=0; say;say '***error!***' arg(1) x;say;say;return </lang>

REBOL

<lang REBOL>REBOL [ Title: "Text Menu" Author: oofoe Date: 2009-12-08 URL: http://rosettacode.org/wiki/Select ]

choices: ["fee fie" "huff and puff" "mirror mirror" "tick tock"] choice: ""

valid?: func [ choices [block! list! series!] choice ][ if error? try [choice: to-integer choice] [return false] all [0 < choice choice <= length? choices] ]

while [not valid? choices choice][ repeat i length? choices [print [" " i ":" choices/:i]] choice: ask "Which is from the three pigs? " ] print ["You chose:" pick choices to-integer choice]</lang>

Output:

   1 : fee fie
   2 : huff and puff
   3 : mirror mirror
   4 : tick tock
Which is from the three pigs? klf
   1 : fee fie
   2 : huff and puff
   3 : mirror mirror
   4 : tick tock
Which is from the three pigs? 5
   1 : fee fie
   2 : huff and puff
   3 : mirror mirror
   4 : tick tock
Which is from the three pigs? 2
You chose: huff and puff

Ruby

<lang ruby>def select(prompt, items)

 return "" if items.length == 0
 while true
   items.each_index {|i| puts "#{i}. #{items[i]}"}
   print "#{prompt}: "
   begin
     answer = Integer(gets())
   rescue ArgumentError
     redo
   end
   return items[answer] if answer.between?(0, items.length - 1)
 end

end

  1. test empty list

response = select("Which is empty", []) puts "empty list returns: >#{response}<" puts ""

  1. "real" test

items = ['fee fie', 'huff and puff', 'mirror mirror', 'tick tock'] response = select("Which is from the three pigs", items) puts "you chose: >#{response}<"</lang>

Tcl

<lang tcl>proc select {prompt choices} {

   set nc [llength $choices]
   if {!$nc} {

return ""

   }
   set numWidth [string length $nc]
   while true {

set i 0 foreach s $choices { puts [format "  %-*d: %s" $numWidth [incr i] $s] } puts -nonewline "$prompt: " flush stdout gets stdin num if {[string is int -strict $num] && $num >= 1 && $num <= $nc} { incr num -1 return [lindex $choices $num] }

   }

}</lang> Testing it out interactively... <lang tcl>% puts >[select test {}]< >< % puts >[select "Which is from the three pigs" {

   "fee fie" "huff and puff" "mirror mirror" "tick tock"

}]<

 1: fee fie
 2: huff and puff
 3: mirror mirror
 4: tick tock

Which is from the three pigs: 0

 1: fee fie
 2: huff and puff
 3: mirror mirror
 4: tick tock

Which is from the three pigs: skdfjhgz

 1: fee fie
 2: huff and puff
 3: mirror mirror
 4: tick tock

Which is from the three pigs:

 1: fee fie
 2: huff and puff
 3: mirror mirror
 4: tick tock

Which is from the three pigs: 5

 1: fee fie
 2: huff and puff
 3: mirror mirror
 4: tick tock

Which is from the three pigs: 2 >huff and puff<</lang>

UNIX Shell

Works with: bash
Works with: pdksh

This example uses bash shell with its select statement. This example also works with other shells, such as pdksh, that provide the select statement.

<lang bash>bash$ PS3='Which is from the three pigs: ' bash$ select phrase in 'fee fie' 'huff and puff' 'mirror mirror' 'tick tock'; do > if -n $phrase ; then > PHRASE=$phrase > echo PHRASE is $PHRASE > break > else > echo 'invalid.' > fi > done 1) fee fie 2) huff and puff 3) mirror mirror 4) tick tock Which is from the three pigs: 5 invalid. Which is from the three pigs: 2 PHRASE is huff and puff bash$</lang>