CloudFlare suffered a massive security issue affecting all of its customers, including Rosetta Code. All passwords not changed since February 19th 2017 have been expired, and session cookie longevity will be reduced until late March.--Michael Mol (talk) 05:15, 25 February 2017 (UTC)

Menu

From Rosetta Code
Task
Menu
You are encouraged to solve this task according to the task description, using any language you may know.
Task

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

  • prints a textual menu formatted as an index value followed by its corresponding string for each item in the list;
  • prompts the user to enter a number;
  • returns the string corresponding to the selected index number.


The function should reject input that is not an integer or is out of range by redisplaying 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 following four phrases in a list:

   fee fie
   huff and puff
   mirror mirror
   tick tock
Note

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

Ada[edit]

 
-- 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;
 
 
 
./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)
 
 

ALGOL 68[edit]

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
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)))
)

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[edit]

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

AWK[edit]

 
# syntax: GAWK -f MENU.AWK
BEGIN {
n = split("fee fie:huff and puff:mirror mirror:tick tock",arr,":")
while (1) {
print("")
for (i=1; i<=n; i++) {
printf("%d - %s\n",i,arr[i])
}
print("0 - exit")
printf("enter number: ")
getline ans
if (ans in arr) {
printf("you picked '%s'\n",arr[ans])
continue
}
if (ans == 0) {
break
}
print("invalid choice")
}
exit(0)
}
 

Axe[edit]

In Axe, static data (such as strings) is laid out sequentially in memory. So the H in "HUFF" is the byte after the null terminator for "FIE". However, null terminators are only added to strings when they are stored with the store symbol →. strGet returns a pointer to the start of the nth null-terminated string in the data, which is why the strings must be laid out in memory correctly.

"FEE FIE"→Str1
"HUFF AND PUFF"→Str2
"MIRROR MIRROR"→Str3
"TICK TOCK"→Str4
For(I,1,4)
Disp I▶Hex+3,":",strGet(Str1,I-1),i
End
Disp "NUMBER? "
input→A
{A}-'0'→N
If N<1 or N>4
Disp "BAD NUMBER",i
Return
End
Disp strGet(Str1,N-1),i

BASIC[edit]

Works with: QuickBasic version 4.5
 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

Batch File[edit]

@echo off
setlocal enabledelayedexpansion

::The Main Thing...

set choices="fee fie","huff and puff","mirror mirror","tick tock"
set "quest=Which is from the three pigs?"
call :select
pause>nul
exit /b 0
::/The Main Thing.

::The Function...

:select
set number=0
for %%A in (%choices%) do set tmpvar=%%A&set /a number+=1&set opt!number!=!tmpvar:"=!
:tryagain
cls&echo.
for /l %%A in (1,1,%number%) do echo. Option %%A - !opt%%A!
echo.
set /p input=%quest%
for /l %%A in (1,1,%number%) do (
if !input! equ %%A echo.&echo.You chose option %%A - !opt%%A!&goto :EOF
)
echo.
echo.Invalid Input. Please try again...
pause>nul
goto tryagain
::/The Function.

BBC BASIC[edit]

      DIM list$(4)
list$() = "fee fie", "huff and puff", "mirror mirror", "tick tock"
selected$ = FNmenu(list$(), "Please make a selection: ")
PRINT selected$
END
 
DEF FNmenu(list$(), prompt$)
LOCAL index%, select$
IF SUM(list$()) = "" THEN = ""
REPEAT
CLS
FOR index% = 0 TO DIM(list$() ,1)
IF list$(index%)<>"" PRINT ; index% ":", list$(index%)
NEXT
PRINT prompt$ ;
INPUT "" select$
index% = VAL(select$)
IF select$<>STR$(index%) index% = -1
IF index%>=0 IF index%<=DIM(list$() ,1) IF list$(index%)="" index% = -1
UNTIL index%>=0 AND index%<=DIM(list$(), 1)
= list$(index%)

Empty entries in the list are not offered as options, nor accepted as a selection.

Brat[edit]

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"]

C[edit]

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
const char *menu_select(const char *const *items, const char *prompt);
 
int
main(void)
{
const char *items[] = {"fee fie", "huff and puff", "mirror mirror", "tick tock", NULL};
const char *prompt = "Which is from the three pigs?";
 
printf("You chose %s.\n", menu_select(items, prompt));
 
return EXIT_SUCCESS;
}
 
const char *
menu_select(const char *const *items, const 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];
}

C++[edit]

#include <iostream>
#include <string>
#include <vector>
 
void print_menu(const std::vector<std::string>& terms)
{
for (size_t i = 0; i < terms.size(); i++) {
std::cout << i + 1 << ") " << terms[i] << '\n';
}
}
 
int parse_entry(const std::string& entry, int max_number)
{
int number = std::stoi(entry);
if (number < 1 || number > max_number) {
throw std::invalid_argument("");
}
 
return number;
}
 
std::string data_entry(const std::string& prompt, const std::vector<std::string>& terms)
{
if (terms.empty()) {
return "";
}
 
int choice;
while (true) {
print_menu(terms);
std::cout << prompt;
 
std::string entry;
std::cin >> entry;
 
try {
choice = parse_entry(entry, terms.size());
return terms[choice - 1];
} catch (std::invalid_argument&) {
// std::cout << "Not a valid menu entry!" << std::endl;
}
}
}
 
int main()
{
std::vector<std::string> terms = {"fee fie", "huff and puff", "mirror mirror", "tick tock"};
std::cout << "You chose: " << data_entry("> ", terms) << std::endl;
}
 

C#[edit]

 
using System;
using System.Collections.Generic;
 
public class Menu
{
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];
}
}
 

Ceylon[edit]

"Run the module `menu`."
shared void run() {
value selection = menu("fee fie", "huff And puff", "mirror mirror", "tick tock");
print(selection);
}
 
String menu(String* strings) {
if(strings.empty) {
return "";
}
value entries = map(zipEntries(1..strings.size, strings));
while(true) {
for(index->string in entries) {
print("``index``) ``string``");
}
process.write("> ");
value input = process.readLine();
if(exists input, exists int = parseInteger(input), exists string = entries[int]) {
return string;
}
}
}
 
 

Clojure[edit]

(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"]))

COBOL[edit]

       IDENTIFICATION DIVISION.
PROGRAM-ID. Test-Prompt-Menu.
 
DATA DIVISION.
WORKING-STORAGE SECTION.
 
01 Num-Options USAGE UNSIGNED-INT VALUE 4.
01 Example-Menu.
03 Example-Options-Data.
05 FILLER PIC X(30) VALUE "fee fie".
05 FILLER PIC X(30) VALUE "huff and puff".
05 FILLER PIC X(30) VALUE "mirror mirror".
05 FILLER PIC X(30) VALUE "tick tock".
 
03 Example-Options-Values REDEFINES Example-Options-Data.
05 Example-Options PIC X(30) OCCURS 4 TIMES.
 
01 Chosen-Option PIC X(30).
 
PROCEDURE DIVISION.
CALL "Prompt-Menu" USING BY CONTENT Num-Options
BY CONTENT Example-Menu
BY REFERENCE Chosen-Option
 
DISPLAY "You chose: " Chosen-Option
 
GOBACK
.
 
END PROGRAM Test-Prompt-Menu.
 
IDENTIFICATION DIVISION.
PROGRAM-ID. Prompt-Menu.
 
DATA DIVISION.
LOCAL-STORAGE SECTION.
01 User-Input USAGE UNSIGNED-INT.
01 Input-Flag PIC X.
88 Valid-Input VALUE "Y".
 
01 Options-Index USAGE UNSIGNED-INT.
01 Index-Display PIC Z(10).
 
LINKAGE SECTION.
 
01 Num-Options USAGE UNSIGNED-INT.
01 Menu-Options.
03 Options-Table PIC X(30) OCCURS 0 TO 10000000 TIMES
DEPENDING ON Num-Options.
 
01 Chosen-Option PIC X(30).
 
PROCEDURE DIVISION USING Num-Options Menu-Options Chosen-Option.
Main.
IF Num-Options = 0
MOVE SPACES TO Chosen-Option
GOBACK
END-IF
 
PERFORM UNTIL Valid-Input
PERFORM Display-Menu-Options
 
DISPLAY "Choose an option: " WITH NO ADVANCING
ACCEPT User-Input
 
PERFORM Validate-Input
END-PERFORM
 
MOVE Options-Table (User-Input) TO Chosen-Option
 
GOBACK
.
 
Display-Menu-Options.
PERFORM VARYING Options-Index FROM 1 BY 1
UNTIL Num-Options < Options-Index
MOVE Options-Index TO Index-Display
DISPLAY
Index-Display ". " Options-Table (Options-Index)
END-DISPLAY
END-PERFORM
.
 
Validate-Input.
IF User-Input = 0 OR > Num-Options
DISPLAY "Invalid input."
ELSE
SET Valid-Input TO TRUE
END-IF
.
 
END PROGRAM Prompt-Menu.

Common Lisp[edit]

(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)))))

D[edit]

import std.stdio, std.conv, std.string, std.array, std.typecons;
 
string menuSelect(in string[] entries) {
static Nullable!(int, -1) validChoice(in string input,
in int nEntries)
pure nothrow {
try {
immutable n = input.to!int;
return typeof(return)((n >= 0 && n <= nEntries) ? n : -1);
} catch (Exception e) // Very generic
return typeof(return)(-1); // Not valid.
}
 
if (entries.empty)
return "";
 
while (true) {
"Choose one:".writeln;
foreach (immutable i, const entry; entries)
writefln("  %d) %s", i, entry);
"> ".write;
immutable input = readln.chomp;
immutable choice = validChoice(input, entries.length - 1);
if (choice.isNull)
"Wrong choice.".writeln;
else
return entries[choice]; // We have a valid choice.
}
}
 
void main() {
immutable items = ["fee fie", "huff and puff",
"mirror mirror", "tick tock"];
writeln("You chose '", items.menuSelect, "'.");
}
Output:
Choose one:
  0) fee fie
  1) huff and puff
  2) mirror mirror
  3) tick tock
> 2
You chose 'mirror mirror'.

Elixir[edit]

defmodule Menu do
def select(_, []), do: ""
def select(prompt, items) do
IO.puts ""
Enum.with_index(items) |> Enum.each(fn {item,i} -> IO.puts " #{i}. #{item}" end)
answer = IO.gets("#{prompt}: ") |> String.strip
case Integer.parse(answer) do
{num, ""} when num in 0..length(items)-1 -> Enum.at(items, num)
_ -> select(prompt, items)
end
end
end
 
# test empty list
response = Menu.select("Which is empty", [])
IO.puts "empty list returns: #{inspect response}"
 
# "real" test
items = ["fee fie", "huff and puff", "mirror mirror", "tick tock"]
response = Menu.select("Which is from the three pigs", items)
IO.puts "you chose: #{inspect response}"
Output:
empty list returns: ""

 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"

ERRE[edit]

 
PROCEDURE Selection(choices$[],prompt$->sel$)
IF UBOUND(choices$,1)-LBOUND(choices$,1)=0 THEN
sel$=""
EXIT PROCEDURE
END IF
ret$=""
REPEAT
FOR i=LBOUND(choices$,1) TO UBOUND(choices$,1) DO
PRINT(i;": ";choices$[i])
END FOR
PRINT(prompt$;)
INPUT(index)
IF index<=UBOUND(choices$,1) AND index>=LBOUND(choices$,1) THEN ret$=choices$[index] END IF
UNTIL ret$<>""
sel$=ret$
END PROCEDURE
 

Euphoria[edit]

include get.e
 
function menu_select(sequence items, object prompt)
if length(items) = 0 then
return ""
else
for i = 1 to length(items) do
printf(1,"%d) %s\n",{i,items[i]})
end for
 
if atom(prompt) then
prompt = "Choice?"
end if
 
return items[prompt_number(prompt,{1,length(items)})]
end if
end function
 
constant items = {"fee fie", "huff and puff", "mirror mirror", "tick tock"}
constant prompt = "Which is from the three pigs? "
 
printf(1,"You chose %s.\n",{menu_select(items,prompt)})

Factor[edit]

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* ;

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[edit]

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")
}
}

Fortran[edit]

Please find the example output along with the build instructions in the comments at the start of the FORTRAN 2008 source. Compiler: gfortran from the GNU compiler collection. Command interpreter: bash.

 
!-*- mode: compilation; default-directory: "/tmp/" -*-
!Compilation started at Mon Jun 3 23:08:36
!
!a=./f && make $a && OMP_NUM_THREADS=2 $a
!gfortran -std=f2008 -Wall -fopenmp -ffree-form -fall-intrinsics -fimplicit-none f.f08 -o f
!
!$ ./f
! Choose fairly a tail
! 1: fee fie
! 2: huff and puff
! 3: mirror mirror
! 4: tick tock
!bad input
! Choose fairly a tail
! 1: fee fie
! 2: huff and puff
! 3: mirror mirror
! 4: tick tock
!^D
!
!STOP Unexpected end of file
!$ ./f
! Choose fairly a tail
! 1: fee fie
! 2: huff and puff
! 3: mirror mirror
! 4: tick tock
!88
! Choose fairly a tail
! 1: fee fie
! 2: huff and puff
! 3: mirror mirror
! 4: tick tock
!-88
! Choose fairly a tail
! 1: fee fie
! 2: huff and puff
! 3: mirror mirror
! 4: tick tock
!3.2
! Choose fairly a tail
! 1: fee fie
! 2: huff and puff
! 3: mirror mirror
! 4: tick tock
!2
! huff and puff
!$
 
module menu
contains
function selector(title, options, n) result(choice)
integer, optional, intent(in) :: n
character(len=*), intent(in) :: title
character(len=*),dimension(:),intent(in) :: options
!character(len=:), allocatable :: choice ! requires deallocation
!allocate(character(len=8)::choice)
character(len=128) :: choice
integer :: i, L, ios
L = merge(n, size(options), present(n))
if (L .lt. 1) stop 'Silly input'
if (len(choice) .lt. len(options(1))) stop 'menu choices are excessively long'
i = 0
do while ((ios.ne.0) .or. ((i.lt.1) .or. (L.lt.i)))
write(6,*) title
write(6,"(i8,': ',a)")(i,options(i),i=1,L)
read(5,*,iostat=ios,end=666) i
end do
choice = options(i)
return
666 continue
stop 'Unexpected end of file'
end function selector
end module menu
 
program menu_demo
use menu
character(len=14), dimension(4) :: items = (/'fee fie ', 'huff and puff ', 'mirror mirror ','tick tock '/)
print*,selector('Choose fairly a tail', items)
end program menu_demo
 

F#[edit]

open System
 
let rec menuChoice (options : string list) prompt =
if options = [] then ""
else
for i = 0 to options.Length - 1 do
printfn "%d. %s" (i + 1) options.[i]
 
printf "%s" prompt
let input = Int32.TryParse(Console.ReadLine())
 
match input with
| true, x when 1 <= x && x <= options.Length -> options.[x - 1]
| _, _ -> menuChoice options prompt
 
[<EntryPoint>]
let main _ =
let menuOptions = ["fee fie"; "huff and puff"; "mirror mirror"; "tick tock"]
let choice = menuChoice menuOptions "Choose one: "
printfn "You chose: %s" choice
 
0

Go[edit]

package main
 
import "fmt"
 
func menu(choices []string, prompt string) string {
if len(choices) == 0 {
return ""
}
var c int
for {
fmt.Println("")
for i, s := range choices {
fmt.Printf("%d.  %s\n", i+1, s)
}
fmt.Print(prompt)
_, err := fmt.Scanln(&c)
 
if err == nil && c > 0 && c <= len(choices) {
break
}
}
return choices[c-1]
}
 
func main() {
pick := menu(nil, "No prompt")
fmt.Printf("No choices, result = %q\n", pick)
 
choices := []string{
"fee fie",
"huff and puff",
"mirror mirror",
"tick tock",
}
pick = menu(choices, "Enter number: ")
fmt.Printf("You picked %q\n", pick)
}

Output:

No choices, result = ""

1.  fee fie
2.  huff and puff
3.  mirror mirror
4.  tick tock
Enter number: 2
You picked "huff and puff"

Haskell[edit]

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

Example usage, at the GHCI prompt:

*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>

HicEst[edit]

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

Icon and Unicon[edit]

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

J[edit]

Solution:

require 'general/misc/prompt' NB. in older versions of J this was: require'misc'
showMenu =: i.@# smoutput@,&":&> ' '&,&.>
makeMsg =: 'Choose a number 0..' , ': ',~ ":@<:@#
errorMsg =: [ smoutput bind 'Please choose a valid number!'
 
select=: ({::~ _&".@prompt@(makeMsg [ showMenu)) :: ($:@errorMsg)

See Talk page for explanation of code.

Example use:

   select 'fee fie'; 'huff and puff'; 'mirror mirror'; 'tick tock'

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[edit]

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;
}

JavaScript[edit]

Works with: JScript
for the I/O.
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]);

jq[edit]

Works with: jq version 1.5

This version uses jq 1.5's 'input' builtin to read programmatically from STDIN.

def choice:
def read(prompt; max):
def __read__:
prompt,
( input as $input
| if ($input|type) == "number" and 0 < $input and $input <= max then $input
else __read__
end);
__read__;
 
if length == 0 then ""
else
. as $in
| ("Enter your choice:\n" +
(reduce range(0; length) as $i (""; . + "\($i + 1): \($in[$i])\n")) ) as $prompt
| read($prompt; length) as $read
| if ($read|type) == "string" then $read
else "Thank you for selecting \($in[$read-1])" end
end ;

Example:

["fee fie", "huff and puff", "mirror mirror", "tick tock"] | choice
 
$ jq -n -r -f Menu.jq
Enter your choice:
1: fee fie
2: huff and puff
3: mirror mirror
4: tick tock
 
5
Enter your choice:
1: fee fie
2: huff and puff
3: mirror mirror
4: tick tock
 
1
Thank you for selecting fee fie

[edit]

Works with: UCB 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])
 

Lua[edit]

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"}

Mathematica[edit]

textMenu[data_List] := (MapIndexed[Print[#2[[1]], ") ", #] &, {a, b, c}];
While[! (IntegerQ[choice] && Length[data] > choice > 0),
choice = Input["Enter selection"]];
data[[choice]])

Use:

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

MATLAB[edit]

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
 

Modula-2[edit]

MODULE  Menu;
 
FROM InOut IMPORT WriteString, WriteCard, WriteLn, ReadCard;
 
CONST StringLength = 100;
MenuSize = 4;
 
TYPE String = ARRAY[0..StringLength-1] OF CHAR;
 
VAR menu : ARRAY[0..MenuSize] OF String;
selection, index : CARDINAL;
 
BEGIN
menu[1] := "fee fie";
menu[2] := "huff and puff";
menu[3] := "mirror mirror";
menu[4] := "tick tock";
 
FOR index := 1 TO HIGH(menu) DO
WriteString("[");
WriteCard( index,1);
WriteString( "] ");
WriteString( menu[index]);
WriteLn;
END;(*of FOR*)
 
WriteString("Choose what you want : ");
ReadCard(selection);
 
IF (selection <= HIGH(menu)) AND (selection > 0) THEN
WriteString("You have chosen: ");
WriteString( menu[selection]);
WriteLn;
ELSE
WriteString("Selection is out of range!");
WriteLn;
END (*of IF*)
END Menu.

MUMPS[edit]

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)
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

Nim[edit]

Translation of: Python
import strutils, rdstdin
 
proc menu(xs) =
for i,x in xs: echo " ",i,") ",x
 
proc ok(reply, count): bool =
try:
let n = parseInt(reply)
return 0 <= n and n < count
except: return false
 
proc selector(xs, prompt): string =
if xs.len == 0: return ""
var reply = "-1"
while not ok(reply, xs.len):
menu(xs)
reply = readLineFromStdin(prompt).strip()
return xs[parseInt(reply)]
 
const xs = ["fee fie", "huff and puff", "mirror mirror", "tick tock"]
let item = selector(xs, "Which is from the three pigs: ")
echo "You chose: ", item

Output:

  0) fee fie
  1) huff and puff
  2) mirror mirror
  3) tick tock
Which is from the three pigs: foo
  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: 2
You chose: mirror mirror

OCaml[edit]

 
let select ?(prompt="Choice? ") = function
| [] -> ""
| choices ->
let rec menu () =
List.iteri (Printf.printf "%d: %s\n") choices;
print_string prompt;
try List.nth choices (read_int ())
with _ -> menu ()
in menu ()
 

Example use in the REPL:

 
# select ["fee fie"; "huff and puff"; "mirror mirror"; "tick tock"];;
0: fee fie
1: huff and puff
2: mirror mirror
3: tick tock
Choice? 2
- : string = "mirror mirror"
 

OpenEdge/Progress[edit]

FUNCTION bashMenu RETURNS CHAR(
i_c AS CHAR
):
 
DEF VAR ii AS INT.
DEF VAR hfr AS HANDLE.
DEF VAR hmenu AS HANDLE EXTENT.
DEF VAR ikey AS INT.
DEF VAR ireturn AS INT INITIAL ?.
 
EXTENT( hmenu ) = NUM-ENTRIES( i_c ).
 
CREATE FRAME hfr ASSIGN
WIDTH = 80
HEIGHT = NUM-ENTRIES( i_c )
PARENT = CURRENT-WINDOW
VISIBLE = TRUE
.
 
DO ii = 1 TO NUM-ENTRIES( i_c ):
 
CREATE TEXT hmenu ASSIGN
FRAME = hfr
FORMAT = "x(79)"
SCREEN-VALUE = SUBSTITUTE( "&1. &2", ii, ENTRY( ii, i_c ) )
ROW = ii
VISIBLE = TRUE
.
 
END.
 
IF i_c = "" THEN
ireturn = 1.
 
DO WHILE ireturn = ?:
 
READKEY.
ikey = INTEGER( CHR( LASTKEY ) ) NO-ERROR.
IF ikey >= 1 AND ikey <= NUM-ENTRIES( i_c ) THEN
ireturn = ikey.
 
END.
 
RETURN ENTRY( ireturn, i_c ).
 
END FUNCTION.
 
MESSAGE
bashMenu( "fee fie,huff and puff,mirror mirror,tick tock" )
VIEW-AS ALERT-BOX.

Oz[edit]

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}

PARI/GP[edit]

choose(v)=my(n);for(i=1,#v,print(i". "v[i]));while(type(n=input())!="t_INT"|n>#v|n<1,);v[n]
choose(["fee fie","huff and puff","mirror mirror","tick tock"])

Pascal[edit]

Works with: Free_Pascal

Tested with Free Pascal 2.6.4 (arm).

program Menu;
{$ASSERTIONS ON}
uses
objects;
var
MenuItems :PUnSortedStrCollection;
selected :string;
 
Function SelectMenuItem(MenuItems :PUnSortedStrCollection):string;
var
i, idx :integer;
code :word;
choice :string;
begin
// Return empty string if the collection is empty.
if MenuItems^.Count = 0 then
begin
SelectMenuItem := '';
Exit;
end;
 
repeat
for i:=0 to MenuItems^.Count-1 do
begin
writeln(i+1:2, ') ', PString(MenuItems^.At(i))^);
end;
write('Make your choice: ');
readln(choice);
// Try to convert choice to an integer.
// Code contains 0 if this was successful.
val(choice, idx, code)
until (code=0) and (idx>0) and (idx<=MenuItems^.Count);
// Return the selected element.
SelectMenuItem := PString(MenuItems^.At(idx-1))^;
end;
 
begin
// Create an unsorted string collection for the menu items.
MenuItems := new(PUnSortedStrCollection, Init(10, 10));
 
// Add some menu items to the collection.
MenuItems^.Insert(NewStr('fee fie'));
MenuItems^.Insert(NewStr('huff and puff'));
MenuItems^.Insert(NewStr('mirror mirror'));
MenuItems^.Insert(NewStr('tick tock'));
 
// Display the menu and get user input.
selected := SelectMenuItem(MenuItems);
writeln('You chose: ', selected);
 
dispose(MenuItems, Done);
 
// Test function with an empty collection.
MenuItems := new(PUnSortedStrCollection, Init(10, 10));
 
selected := SelectMenuItem(MenuItems);
// Assert that the function returns an empty string.
assert(selected = '', 'Assertion failed: the function did not return an empty string.');
 
dispose(MenuItems, Done);
end.
Output:
$ bin/menu 
 1) fee fie
 2) huff and puff
 3) mirror mirror
 4) tick tock
Make your choice: abc
 1) fee fie
 2) huff and puff
 3) mirror mirror
 4) tick tock
Make your choice: 99
 1) fee fie
 2) huff and puff
 3) mirror mirror
 4) tick tock
Make your choice: 3
You chose: mirror mirror

Perl[edit]

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";

Perl 6[edit]

sub menu ( $prompt, @items ) {
return '' unless @items.elems;
repeat until my $selection ~~ /^ \d+ $/ && @items[--$selection] {
my $i = 1;
say " {$i++}) $_" for @items;
$selection = prompt $prompt;
}
return @items[$selection];
}
 
my @choices = 'fee fie', 'huff and puff', 'mirror mirror', 'tick tock';
my $prompt = 'Enter the number corresponding to your selection: ';
 
my $answer = menu( $prompt, [] );
say "You chose: $answer" if $answer.chars;
 
$answer = menu( $prompt, @choices );
say "You chose: $answer" if $answer.chars;

PL/I[edit]

 
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;
 

Phix[edit]

Slightly modified copy of Euphoria

function menu_select(sequence items, object prompt)
sequence res
integer nres
if length(items)=0 then return 0 end if
while 1 do
for i = 1 to length(items) do
printf(1,"%d) %s\n",{i,items[i]})
end for
 
puts(1,iff(atom(prompt)?"Choice?":prompt))
res = scanf(trim(gets(0)),"%d")
puts(1,"\n")
if length(res)=1 then
nres = res[1][1]
if nres>0 and nres<=length(items) then exit end if
end if
end while
return nres
end function
 
constant items = {"fee fie", "huff and puff", "mirror mirror", "tick tock"}
integer n = menu_select(items,"Which is from the three pigs? ")
printf(1,"You chose %d(%s).\n",{n,items[n]})

PHP[edit]

<?php
$stdin = fopen("php://stdin", "r");
$allowed = array(1 => 'fee fie', 'huff and puff', 'mirror mirror', 'tick tock');
 
for(;;) {
foreach ($allowed as $id => $name) {
echo " $id: $name\n";
}
echo "Which is from the four pigs: ";
$stdin_string = fgets($stdin, 4096);
if (isset($allowed[(int) $stdin_string])) {
echo "You chose: {$allowed[(int) $stdin_string]}\n";
break;
}
}

PicoLisp[edit]

(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") )

Output:

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


PowerShell[edit]

 
function Select-TextItem
{
<#
.SYNOPSIS
Prints a textual menu formatted as an index value followed by its corresponding string for each object in the list.
.DESCRIPTION
Prints a textual menu formatted as an index value followed by its corresponding string for each object in the list;
Prompts the user to enter a number;
Returns an object corresponding to the selected index number.
.PARAMETER InputObject
An array of objects.
.PARAMETER Prompt
The menu prompt string.
.EXAMPLE
“fee fie”, “huff and puff”, “mirror mirror”, “tick tock” | Select-TextItem
.EXAMPLE
“huff and puff”, “fee fie”, “tick tock”, “mirror mirror” | Sort-Object | Select-TextItem -Prompt "Select a string"
.EXAMPLE
Select-TextItem -InputObject (Get-Process)
.EXAMPLE
(Get-Process | Where-Object {$_.Name -match "notepad"}) | Select-TextItem -Prompt "Select a Process" | Stop-Process -ErrorAction SilentlyContinue
#>

[CmdletBinding()]
Param
(
[Parameter(Mandatory=$true,
ValueFromPipeline=$true)]
$InputObject,
 
[Parameter(Mandatory=$false)]
[string]
$Prompt = "Enter Selection"
)
 
Begin
{
$menuOptions = @()
}
Process
{
$menuOptions += $InputObject
}
End
{
do
{
[int]$optionNumber = 1
 
foreach ($option in $menuOptions)
{
Write-Host ("{0,3}: {1}" -f $optionNumber,$option)
 
$optionNumber++
}
 
Write-Host ("{0,3}: {1}" -f 0,"To cancel")
 
[int]$choice = Read-Host $Prompt
 
$selectedValue = ""
 
if ($choice -gt 0 -and $choice -le $menuOptions.Count)
{
$selectedValue = $menuOptions[$choice - 1]
}
}
until ($choice -eq 0 -or $choice -le $menuOptions.Count)
 
return $selectedValue
}
}
 
“fee fie”, “huff and puff”, “mirror mirror”, “tick tock” | Select-TextItem -Prompt "Select a string"
 
Output:
  1: fee fie
  2: huff and puff
  3: mirror mirror
  4: tick tock
  0: To cancel
Select a string: 3
mirror mirror

ProDOS[edit]

 
:a
printline ==========MENU==========
printline 1. Fee Fie
printline 2. Huff Puff
printline 3. Mirror, Mirror
printline 4. Tick, Tock
editvar /newvar /value=a /userinput=1 /title=What page do you want to go to?
if -a- /hasvalue 1 printline You chose a line from the book Jack and the Beanstalk. & exitcurrentprogram 1
if -a- /hasvalue 2 printline You chose a line from the book The Three Little Pigs. & exitcurrentprogram 1
if -a- /hasvalue 3 printline You chose a line from the book Snow White. & exitcurrentprogram 1
if -a- /hasvalue 4 printline You chose a line from the book Beauty and the Beast. & exitcurrentprogram 1
printline You either chose an invalid choice or didn't chose.
editvar /newvar /value=goback /userinput=1 /title=Do you want to chose something else?
if -goback- /hasvalue y goto :a else exitcurrentprogram 1

Prolog[edit]

Works with: SWI-Prolog version 6
 
rosetta_menu([], "") :- !. %% Incase of an empty list.
rosetta_menu(Items, SelectedItem) :-
repeat, %% Repeat until everything that follows is true.
display_menu(Items), %% IO
get_choice(Choice), %% IO
number(Choice), %% True if Choice is a number.
nth1(Choice, Items, SelectedItem), %% True if SelectedItem is the 1-based nth member of Items, (fails if Choice is out of range)
!.
 
display_menu(Items) :-
nl,
foreach( nth1(Index, Items, Item),
format('~w) ~s~n', [Index, Item]) ).
 
get_choice(Choice) :-
prompt1('Select a menu item by number:'),
read(Choice).
 

Example run:

 
?- rosetta_menu(["fee fie", "huff and puff", "mirror mirror", "tick tock"], String).
 
1) fee fie
2) huff and puff
3) mirror mirror
4) tick tock
Select a menu item by number:a.
 
1) fee fie
2) huff and puff
3) mirror mirror
4) tick tock
Select a menu item by number:10.
 
1) fee fie
2) huff and puff
3) mirror mirror
4) tick tock
Select a menu item by number:3.
String = "mirror mirror".
 

PureBasic[edit]

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

Python[edit]

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)

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[edit]

Uses menu.

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

Racket[edit]

 
#lang racket
 
(define (menu choices)
(cond [(null? choices) ""]
[else (for ([c choices] [i (in-naturals 1)]) (printf "~a. ~a\n" i c))
(printf "Enter a number: ")
(define n (string->number (read-line)))
(or (and (exact-integer? n)
(<= 1 n (length choices))
(list-ref choices (sub1 n)))
(menu choices))]))
 
(menu '("fee fie" "huff and puff" "mirror mirror" "tick tock"))
 

Sample Run:

1. fee fie
2. huff and puff
3. mirror mirror
4. tick tock
Enter a number: three
1. fee fie
2. huff and puff
3. mirror mirror
4. tick tock
Enter a number: help
1. fee fie
2. huff and puff
3. mirror mirror
4. tick tock
Enter a number: 3!!
1. fee fie
2. huff and puff
3. mirror mirror
4. tick tock
Enter a number: 3
"mirror mirror"

REXX[edit]

/*REXX program displays a list,  then prompts the user for a selection number (integer).*/
do forever /*keep prompting until response is OK. */
call list_create /*create the list from scratch. */
call list_show /*display (show) the list to the user.*/
if #==0 then return '' /*if list is empty, then return null.*/
say right(' choose an item by entering a number from 1 ───►' #, 70, '═')
parse pull x /*get the user's choice (if any). */
 
select
when x='' then call sayErr "a choice wasn't entered"
when words(x)\==1 then call sayErr 'too many choices entered:'
when \datatype(x,'N') then call sayErr "the choice isn't numeric:"
when \datatype(x,'W') then call sayErr "the choice isn't an integer:"
when x<1 | x># then call sayErr "the choice isn't within range:"
otherwise leave /*this leaves the DO FOREVER loop.*/
end /*select*/
end /*forever*/
/*user might've entered 2. or 003 */
x=x/1 /*normalize the number (maybe). */
say; say 'you chose item' x": " #.x
return #.x /*stick a fork in it, we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
list_create: #.1= 'fee fie' /*this is one method for list-building.*/
#.2= 'huff and puff'
#.3= 'mirror mirror'
#.4= 'tick tock'
#=4 /*store the number of choices in # */
return /*(above) is just one convention. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
list_show: say /*display a blank line. */
do j=1 for # /*display the list of choices. */
say '[item' j"] " #.j /*display item number with its choice. */
end /*j*/
say /*display another blank line. */
return
/*──────────────────────────────────────────────────────────────────────────────────────*/
sayErr: say; say '***error***' arg(1) x; say; return

output   (which includes what the user entered:

[item 1]  fee fie
[item 2]  huff and puff
[item 3]  mirror mirror
[item 4]  tick tock

════════════════════ choose an item by entering a number from 1 ───► 4
2           ◄■■■■■■■■■■■■■■■■■■■■■■ what the user entered at the terminal.

you chose item 2:  huff and puff

REBOL[edit]

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]

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

Ring[edit]

 
aList = ["fee fie", "huff and puff", "mirror mirror", "tick tock"]
selected = menu(aList, "please make a selection: ")
see "" + selected + nl
 
func menu aList, prompt
ndex = 1
while index>0 and index<=len(aList)
for index = 1 to len(aList)
if aList[index]!="" see "" + index + " : " + aList[index] + " " ok
next
see nl
see prompt
give select
index = number(select)
see "" + aList[index] + nl
if select!=string(index) index = -1 ok
if index>=0 if index<=len(aList) if aList[index]="" index = -1 ok ok ok
end
return aList[index]
 

Output:

1 : fee fie 2 : huff and puff 3 : mirror mirror 4 : tick tock
please make a selection: 2
huff and puff
1 : fee fie 2 : huff and puff 3 : mirror mirror 4 : tick tock
please make a selection: 1
fee fie
1 : fee fie 2 : huff and puff 3 : mirror mirror 4 : tick tock
please make a selection: 4
tick tock
1 : fee fie 2 : huff and puff 3 : mirror mirror 4 : tick tock
please make a selection: 3
mirror mirror

Ruby[edit]

 
def select(prompt, items = [])
if items.empty?
''
else
answer = -1
until (0...items.length).cover?(answer)
items.each_with_index {|i,j| puts "#{j}. #{i}"}
print "#{prompt}: "
begin
answer = Integer(gets)
rescue ArgumentError
redo
end
end
items[answer]
end
end
 
# test empty list
response = select('Which is empty')
puts "empty list returns: >#{response}<\n"
 
# "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}<"
 

Run BASIC[edit]

dim choose$(5)
choose$(1) = "1 Fee Fie"
choose$(2) = "2 Huff Puff"
choose$(3) = "3 Mirror, Mirror"
choose$(4) = "4 Tick, Tock"
choose$(5) = "Exit"
 
[start]
print "Menu Selection"
listbox #lb,choose$(),5
button #sel, "Accept",[select]
wait
 
[select]
selected$=#lb selection$()
print " "
if selected$<>"" then
print "You selected ";selected$
else
print "No selection made"
end if
button #con, "Continue",[go2]
wait
[go2]
if selected$<>"Exit" then
cls
goto [start]
else
cls
end
end if

Seed7[edit]

$ include "seed7_05.s7i";
 
const func string: menuSelect (in array string: items, in string: prompt) is func
result
var string: selection is "";
local
var string: item is "";
var integer: index is 0;
var integer: num is 0;
begin
if length(items) <> 0 then
repeat
for item key index range items do
writeln(index <& ". " <& item);
end for;
write(prompt);
readln(num);
until num >= 1 and num <= length(items);
selection := items[num];
end if
end func;
 
const array string: items is [] ("fee fie", "huff and puff", "mirror mirror", "tick tock");
const string: prompt is "Which is from the three pigs? ";
 
const proc: main is func
begin
writeln("You chose " <& menuSelect(items, prompt));
end func;

Sidef[edit]

func menu (prompt, arr) {
arr.len > 0 || return ''
loop {
for i in ^arr {
say " #{i}: #{arr[i]}"
}
var n = Sys.scanln(prompt) \\ return()
n ~~ /^[0-9]+\z/ ? Num(n) : next
arr.exists(n) && return arr[n]
}
}
 
var list = ['fee fie', 'huff and puff', 'mirror mirror', 'tick tock']
var prompt = 'Please choose an item number: '
 
var answer = menu(prompt, list)
say "You choose: #{answer}"

Tcl[edit]

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]
}
}
}

Testing it out interactively...

% 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<

TI-83 BASIC[edit]

TI-83 BASIC does not support lists of strings, so this works by accepting a string containing an arbitrary number of items separated by colons. If you want to use a different delimiter, change the colons on lines 2, 3, 6 and 7 to your symbol of choice.

The calculator's screen isn't big enough to display more than 7 (9 on the new C Silver Edition and CE calcs) options at a time, so the display scrolls to accommodate options if necessary. You won't be able to see options that have scrolled off the top of the screen, but they're still accessible from the input.

Although TI-BASIC can handle empty strings, there's no way to give it one through the Input function, so it doesn't have to worry about being "called with an empty list."

Input "",Str1 //input as ITEM 1:ITEM 2:ITEM 3...
":"+Str1+":→Str1
Σ(sub(Str1,X,1)=":",X,1,length(Str1→X
0→dim(L₁
For(Z,2,length(Str1
inString(Str1,":",Z-1
1+Ans+.01inString(Str1,":",Ans+1→L₁(1+dim(L₁
ᴇ2fPart(Ans→Z
End
seq(iPart(L₁(X))+.01(ᴇ2fPart(L₁(X))-iPart(L₁(X))),X,1,dim(L₁→L₁
Repeat A>0 and A<X
ClrHome
For(Z,1,dim(L₁
Disp "  :"+sub(Str1,iPart(L₁(Z)),ᴇ2fPart(L₁(Z
Output(min(7,Z),1+(Z≤7),Z
End
Input A
End
Disp sub(Str1,iPart(L₁(A)),ᴇ2fPart(L₁(A

Output with FEE FIE:HUFF AND PUFF:MIRROR MIRROR:TICK TOCK

 1:FEE FIE
2:HUFF AND PUFF
3:MIRROR MIRROR
4:TICK TOCK
? [flashing cursor]


The language also has a Menu( command, but it doesn't really follow the requirements for the challenge (only up to 7 options allowed, no user input, option is selected using the arrow keys instead of by entering a number, etc)

"FEE FIE→Str0
"HUFF AND PUFF→Str1
"MIRROR MIRROR→Str2
"TICK TOCK→Str3
Menu("CHOOSE",Str0,A,Str1,B,Str2,C,Str3,D)
Lbl A
Disp Str0
Return
Lbl B
Disp Str1
Return
Lbl C
Disp Str2
Return
Lbl D
Disp Str3

UNIX Shell[edit]

This example uses the Bash select statement, but Bash did not invent this feature. The select loop comes originally from the Korn Shell, and appears in some other shells. This loop always continues to read menu choices until the script breaks the loop, or the standard input reaches end of file (EOF).

  • If the user enters a blank line, the select loop repeats the list of choices. This is the only way to print the list again. An invalid choice only repeats the prompt, not the list.

Our choose function wraps a select loop. This wrapper implements the task requirement to provide an empty string from an empty list of choices. It also breaks the select loop after the first good choice.

Works with: bash
Works with: ksh93
Works with: pdksh
Works with: zsh
# choose 'choice 1' 'choice 2' ...
# Prints menu to standard error. Prompts with PS3.
# Reads REPLY from standard input. Sets CHOICE.
choose() {
CHOICE= # Default CHOICE is empty string.
[[ $# -gt 0 ]] || return # Return if "$@" is empty.
select CHOICE; do # Select from "$@".
if [[ -n $CHOICE ]]; then
break
else
echo Invalid choice.
fi
done
}
 
PS3='Which is from the three pigs: '
choose 'fee fie' 'huff and puff' 'mirror mirror' 'tick tock'
[[ -n $CHOICE ]] && echo You chose: $CHOICE
[[ -z $CHOICE ]] && echo No input.
$ bash menu.sh                                                              
1) fee fie
2) huff and puff
3) mirror mirror
4) tick tock
Which is from the three pigs: 5
Invalid choice.
Which is from the three pigs: 2
You chose: huff and puff
$
$ zsh menu.sh                                                               
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

es[edit]

There is no select loop, but this es script provides just enough code to mimic one.

  • Deviation from task: When the list of choices is empty, this function returns an empty list, not an empty string.
# choose 'choice 1' 'choice 2' ...
# Prints menu to standard error. Prompts with $prompt.
# Returns choice. If no input, returns empty list.
fn choose args {
# If args are empty, return empty list.
~ $#args 0 && return
 
# Echo to standard error.
let (reply =; choice =; fn-menu =; fn-ch =) >[1=2] {
fn-menu = {
# Show menu.
let (i = 1) for (c = $args) {
echo $i') '$c
i = `{expr $i + 1}
}
}
fn-ch = {
# Set choice = $args($reply), but ignore error
# if $reply is not a valid index.
choice = <={catch @ e {result} {
result $args($reply)
}}
}
 
menu
forever {
# Show prompt, read reply.
echo -n $prompt
reply = <={%read}
 
# If no input, return empty list.
~ $#reply 0 && return
 
# Parse reply and return choice.
reply = <={%split \ \t\n $reply}
if {~ $#reply 0} {
# Empty reply: show menu again.
menu
} {~ $#reply 1 && ch; ~ $#choice 1} {
return $choice
} {
echo Invalid choice.
}
}
}
}
 
let (choice = <={
local (prompt = 'Which is from the three pigs: ')
choose 'fee fie' 'huff and puff' 'mirror mirror' 'tick tock'
}) {
~ $#choice 1 && echo You chose: $choice
~ $#choice 0 && echo No input.
}
$ es menu.es 
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

Ursa[edit]

Translation of: Python
def _menu (string<> items)
for (decl int i) (< i (size items)) (inc i)
out " " i ") " items<i> endl console
end for
end _menu
 
def _ok (string reply, int itemcount)
try
decl int n
set n (int reply)
return (and (or (> n 0) (= n 0)) (< n itemcount))
catch
return false
end try
end _ok
 
def selector (string<> items, string prompt)
# Prompt to select an item from the items
if (= (size items) 0)
return ""
end if
decl int itemcount reply
set reply -1
set itemcount (size items)
while (not (_ok reply itemcount))
_menu items
out prompt console
set reply (in int console)
end while
return items<(int reply)>
end selector
 
decl string<> items
append "fee fie" "huff and puff" "mirror mirror" "tick tock" items
decl string item
set item (selector items "Which is from the three pigs: ")
out "You chose: " item endl console

VBScript[edit]

 
Do
WScript.StdOut.Write "1. fee fie" & vbCrLf
WScript.StdOut.Write "2. huff puff" & vbCrLf
WScript.StdOut.Write "3. mirror mirror" & vbCrLf
WScript.StdOut.Write "4. tick tock" & vbCrLf
WScript.StdOut.Write "Please Enter Your Choice: " & vbCrLf
choice = WScript.StdIn.ReadLine
Select Case choice
Case "1"
WScript.StdOut.Write "fee fie" & vbCrLf
Exit Do
Case "2"
WScript.StdOut.Write "huff puff" & vbCrLf
Exit Do
Case "3"
WScript.StdOut.Write "mirror mirror" & vbCrLf
Exit Do
Case "4"
WScript.StdOut.Write "tick tock" & vbCrLf
Exit Do
Case Else
WScript.StdOut.Write choice & " is an invalid choice. Please try again..." &_
vbCrLf & vbCrLf
End Select
Loop
 
Output:

F:\>cscript /nologo menu.vbs
1. fee fie
2. huff puff
3. mirror mirror
4. tick tock
Please Enter Your Choice:
9
9 is an invalid choice. Please try again...

1. fee fie
2. huff puff
3. mirror mirror
4. tick tock
Please Enter Your Choice:
f
f is an invalid choice. Please try again...

1. fee fie
2. huff puff
3. mirror mirror
4. tick tock
Please Enter Your Choice:
3
mirror mirror

XPL0[edit]

include c:\cxpl\codes;
string 0;
 
func Menu(List);
int List;
int Size, I, C;
[Size:= List(0);
if Size < 1 then return List(0);
for I:= 1 to Size-1 do
[IntOut(0, I); Text(0, ": ");
Text(0, List(I)); CrLf(0);
];
CrLf(0);
Text(0, List(Size)); \display prompt
loop [C:= ChIn(0); \buffered keyboard requires Enter key
if C>=^1 & C<=Size-1+^0 then return List(C-^0);
Text(0, "Please enter 1 thru "); IntOut(0, Size-1);
Text(0, ": ");
];
];
 
Text(0, Menu([5, "fee fie", "huff and puff", "mirror mirror", "tick tock",
"Which phrase is from the Three Little Pigs? "]))

Example output:

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

Which phrase is from the Three Little Pigs? 5
Please enter 1 thru 4: 2
huff and puff

zkl[edit]

fcn teleprompter(options){
os:=T("exit").extend(vm.arglist); N:=os.len();
if(N==1) return("");
while(1){
Utils.zipWith(fcn(n,o){"%d) %s".fmt(n,o).println()},[0..],os);
a:=ask("Your choice: ");
try{ n:=a.toInt(); if(0<=n<N) return(os[n]); } catch{}
println("Ack, not good");
}
}
 
teleprompter("fee fie" , "huff and puff" , "mirror mirror" , "tick tock")
.println();
Output:
0) exit
1) fee fie
2) huff and puff
3) mirror mirror
4) tick tock
Your choice: abc
Ack, not good
0) exit
1) fee fie
2) huff and puff
3) mirror mirror
4) tick tock
Your choice: 3
mirror mirror