1# ex:ts=8 sw=4: 2# $OpenBSD: Interactive.pm,v 1.21 2016/06/24 14:20:49 espie Exp $ 3# 4# Copyright (c) 2005-2007 Marc Espie <espie@openbsd.org> 5# 6# Permission to use, copy, modify, and distribute this software for any 7# purpose with or without fee is hereby granted, provided that the above 8# copyright notice and this permission notice appear in all copies. 9# 10# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 17use strict; 18use warnings; 19 20package OpenBSD::Interactive; 21 22sub new 23{ 24 my ($class, $state, $level) = @_; 25 bless { 26 state => $state, 27 always => 0, 28 level => $level, 29 }, $class; 30} 31 32sub ask_list 33{ 34 my ($self, $prompt, @values) = @_; 35 if ($self->{always}) { 36 return $values[0]; 37 } 38 my ($fh, $pid); 39 if ($self->{state}->height <= @values + 1) { 40 $pid = open($fh, "|-", "more", "-ce"); 41 } 42 43 $fh //= \*STDERR; 44 45 $self->{state}->fhsay($fh, '#1', $prompt); 46 my $i = 0; 47 for my $v (@values) { 48 $self->{state}->fhsay($fh, "#1\t#2: #3", 49 $i == 0 ? "a" : "", $i, $v); 50 $i++; 51 } 52 if (defined $pid) { 53 close($fh); 54 waitpid $pid, 0; 55 } 56LOOP: 57 $self->{state}->errprint("Your choice: "); 58 my $result = <STDIN>; 59 unless (defined $result) { 60 $self->{state}->errsay(""); 61 return $values[0]; 62 } 63 chomp $result; 64 if ($result eq '') { 65 return $values[0]; 66 } 67 if ($result eq 'a') { 68 $self->{always} = 1; 69 return $values[0]; 70 } 71 if ($result =~ m/^\d+$/o) { 72 if ($result >= 0 && $result < @values) { 73 return $values[$result]; 74 } 75 $self->{state}->errsay("invalid numeric value !"); 76 goto LOOP; 77 } 78 if (grep { $result eq $_ } @values) { 79 return $result; 80 } else { 81 $self->{state}->errsay("Ambiguous value !"); 82 goto LOOP; 83 } 84} 85 86sub confirm 87{ 88 my ($self, $prompt, $yesno) = @_; 89 if ($self->{always}) { 90 return 1; 91 } 92LOOP2: 93 $self->{state}->errprint("#1 ? [#2/a] ", 94 $prompt, $yesno ? "Y/n" : "y/N"); 95 96 my $result = <STDIN>; 97 unless(defined $result) { 98 $self->{state}->errsay(""); 99 return $yesno; 100 } 101 chomp $result; 102 $result =~ s/\s+//go; 103 $result =~ tr/A-Z/a-z/; 104 if ($result eq 'yes' or $result eq 'y') { 105 return 1; 106 } 107 if ($result eq 'no' or $result eq 'n') { 108 return 0; 109 } 110 if ($result eq 'a') { 111 $self->{always} = 1; 112 return 1; 113 } 114 if ($result eq '') { 115 return $yesno; 116 } 117 $self->{state}->errsay("Ambiguous answer"); 118 goto LOOP2; 119} 120 121sub is_interactive 122{ 123 return shift->{level}; 124} 125 1261; 127