]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - make/console.pm
Merge branch 'insp20' into insp3.
[user/henk/code/inspircd.git] / make / console.pm
1 #
2 # InspIRCd -- Internet Relay Chat Daemon
3 #
4 #   Copyright (C) 2014-2017 Peter Powell <petpow@saberuk.com>
5 #
6 # This file is part of InspIRCd.  InspIRCd is free software: you can
7 # redistribute it and/or modify it under the terms of the GNU General Public
8 # License as published by the Free Software Foundation, version 2.
9 #
10 # This program is distributed in the hope that it will be useful, but WITHOUT
11 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12 # FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
13 # details.
14 #
15 # You should have received a copy of the GNU General Public License
16 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 #
18
19
20 package make::console;
21
22 BEGIN {
23         require 5.10.0;
24 }
25
26 use feature ':5.10';
27 use strict;
28 use warnings FATAL => qw(all);
29
30 use Class::Struct         qw(struct);
31 use Exporter              qw(import);
32 use File::Path            qw(mkpath);
33 use File::Spec::Functions qw(rel2abs);
34
35 our @EXPORT = qw(command
36                  execute_command
37                  print_format
38                  print_error
39                  print_warning
40                  prompt_bool
41                  prompt_dir
42                  prompt_string);
43
44 my %FORMAT_CODES = (
45         DEFAULT   => "\e[0m",
46         BOLD      => "\e[1m",
47         UNDERLINE => "\e[4m",
48
49         RED    => "\e[1;31m",
50         GREEN  => "\e[1;32m",
51         YELLOW => "\e[1;33m",
52         BLUE   => "\e[1;34m"
53 );
54
55 my %commands;
56
57 struct 'command' => {
58         'callback'    => '$',
59         'description' => '$',
60 };
61
62 sub __console_format($$) {
63         my ($name, $data) = @_;
64         return $data unless -t STDOUT;
65         return $FORMAT_CODES{uc $name} . $data . $FORMAT_CODES{DEFAULT};
66 }
67
68 sub print_format($;$) {
69         my $message = shift;
70         my $stream = shift // *STDOUT;
71         while ($message =~ /(<\|(\S+)\s(.*?)\|>)/) {
72                 my $formatted = __console_format $2, $3;
73                 $message =~ s/\Q$1\E/$formatted/;
74         }
75         print { $stream } $message;
76 }
77
78 sub print_error {
79         print_format "<|RED Error:|> ", *STDERR;
80         for my $line (@_) {
81                 print_format "$line\n", *STDERR;
82         }
83         exit 1;
84 }
85
86 sub print_warning {
87         print_format "<|YELLOW Warning:|> ", *STDERR;
88         for my $line (@_) {
89                 print_format "$line\n", *STDERR;
90         }
91 }
92
93 sub prompt_bool($$$) {
94         my ($interactive, $question, $default) = @_;
95         while (1) {
96                 my $answer = prompt_string($interactive, $question, $default ? 'yes' : 'no');
97                 return 1 if $answer =~ /^y(?:es)?$/i;
98                 return 0 if $answer =~ /^no?$/i;
99                 print_warning "\"$answer\" is not \"yes\" or \"no\". Please try again.\n";
100         }
101 }
102
103 sub prompt_dir($$$;$) {
104         my ($interactive, $question, $default, $create_now) = @_;
105         my ($answer, $create);
106         do {
107                 $answer = rel2abs(prompt_string($interactive, $question, $default));
108                 $create = prompt_bool($interactive && !-d $answer, "$answer does not exist. Create it?", 'y');
109                 if ($create && $create_now) {
110                         unless (create_directory $answer, 0750) {
111                                 print_warning "unable to create $answer: $!\n";
112                                 $create = 0;
113                         }
114                 }
115         } while (!$create);
116         return $answer;
117 }
118
119 sub prompt_string($$$) {
120         my ($interactive, $question, $default) = @_;
121         return $default unless $interactive;
122         print_format "$question\n";
123         print_format "[<|GREEN $default|>] => ";
124         chomp(my $answer = <STDIN>);
125         say '';
126         return $answer ? $answer : $default;
127 }
128
129 sub command($$$) {
130         my ($name, $description, $callback) = @_;
131         $commands{$name} = command->new;
132         $commands{$name}->callback($callback);
133         $commands{$name}->description($description);
134 }
135
136 sub command_alias($$) {
137         my ($source, $target) = @_;
138         command $source, undef, sub(@) {
139                 execute_command $target, @_;
140         };
141 }
142
143 sub execute_command(@) {
144         my $command = defined $_[0] ? lc shift : 'help';
145         if ($command eq 'help') {
146                 print_format "<|GREEN Usage:|> $0 <<|UNDERLINE COMMAND|>> [<|UNDERLINE OPTIONS...|>]\n\n";
147                 print_format "<|GREEN Commands:|>\n";
148                 for my $key (sort keys %commands) {
149                         next unless defined $commands{$key}->description;
150                         my $name = sprintf "%-15s", $key;
151                         my $description = $commands{$key}->description;
152                         print_format "  <|BOLD $name|> # $description\n";
153                 }
154                 exit 0;
155         } elsif (!$commands{$command}) {
156                 print_error "no command called <|BOLD $command|> exists!",
157                         "See <|BOLD $0 help|> for a list of commands.";
158         } else {
159                 return $commands{$command}->callback->(@_);
160         }
161 }
162
163 1;