xref: /openbsd-src/usr.sbin/pkg_add/OpenBSD/Interactive.pm (revision f2da64fbbbf1b03f09f390ab01267c93dfd77c4c)
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