]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - make/console.pm
Export console_format from make::console and make it more robust.
[user/henk/code/inspircd.git] / make / console.pm
1 #
2 # InspIRCd -- Internet Relay Chat Daemon
3 #
4 #   Copyright (C) 2014-2017, 2019 Sadie Powell <sadie@witchery.services>
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                  console_format
38                  print_format
39                  print_error
40                  print_warning
41                  prompt_bool
42                  prompt_dir
43                  prompt_string);
44
45 my %FORMAT_CODES = (
46         DEFAULT   => "\e[0m",
47         BOLD      => "\e[1m",
48         UNDERLINE => "\e[4m",
49
50         RED    => "\e[1;31m",
51         GREEN  => "\e[1;32m",
52         YELLOW => "\e[1;33m",
53         BLUE   => "\e[1;34m"
54 );
55
56 my %commands;
57
58 struct 'command' => {
59         'callback'    => '$',
60         'description' => '$',
61 };
62
63 sub console_format($) {
64         my $message = shift;
65         while ($message =~ /(<\|(\S+)\s(.*?)\|>)/) {
66                 my ($match, $type, $text) = ($1, uc $2, $3);
67                 if (-t STDOUT && exists $FORMAT_CODES{$type}) {
68                         $message =~ s/\Q$match\E/$FORMAT_CODES{$type}$text$FORMAT_CODES{DEFAULT}/;
69                 } else {
70                         $message =~ s/\Q$match\E/$text/;
71                 }
72         }
73         return $message;
74 }
75
76 sub print_format($;$) {
77         my $message = shift;
78         my $stream = shift // *STDOUT;
79         print { $stream } console_format $message;
80 }
81
82 sub print_error {
83         print_format "<|RED Error:|> ", *STDERR;
84         for my $line (@_) {
85                 print_format "$line\n", *STDERR;
86         }
87         exit 1;
88 }
89
90 sub print_warning {
91         print_format "<|YELLOW Warning:|> ", *STDERR;
92         for my $line (@_) {
93                 print_format "$line\n", *STDERR;
94         }
95 }
96
97 sub prompt_bool($$$) {
98         my ($interactive, $question, $default) = @_;
99         while (1) {
100                 my $answer = prompt_string($interactive, $question, $default ? 'yes' : 'no');
101                 return 1 if $answer =~ /^y(?:es)?$/i;
102                 return 0 if $answer =~ /^no?$/i;
103                 print_warning "\"$answer\" is not \"yes\" or \"no\". Please try again.\n";
104         }
105 }
106
107 sub prompt_dir($$$;$) {
108         my ($interactive, $question, $default, $create_now) = @_;
109         my ($answer, $create);
110         do {
111                 $answer = rel2abs(prompt_string($interactive, $question, $default));
112                 $create = prompt_bool($interactive && !-d $answer, "$answer does not exist. Create it?", 'y');
113                 if ($create && $create_now) {
114                         unless (create_directory $answer, 0750) {
115                                 print_warning "unable to create $answer: $!\n";
116                                 $create = 0;
117                         }
118                 }
119         } while (!$create);
120         return $answer;
121 }
122
123 sub prompt_string($$$) {
124         my ($interactive, $question, $default) = @_;
125         return $default unless $interactive;
126         print_format "$question\n";
127         print_format "[<|GREEN $default|>] => ";
128         chomp(my $answer = <STDIN>);
129         say '';
130         return $answer ? $answer : $default;
131 }
132
133 sub command($$$) {
134         my ($name, $description, $callback) = @_;
135         $commands{$name} = command->new;
136         $commands{$name}->callback($callback);
137         $commands{$name}->description($description);
138 }
139
140 sub command_alias($$) {
141         my ($source, $target) = @_;
142         command $source, undef, sub(@) {
143                 execute_command $target, @_;
144         };
145 }
146
147 sub execute_command(@) {
148         my $command = defined $_[0] ? lc shift : 'help';
149         if ($command eq 'help') {
150                 print_format "<|GREEN Usage:|> $0 <<|UNDERLINE COMMAND|>> [<|UNDERLINE OPTIONS...|>]\n\n";
151                 print_format "<|GREEN Commands:|>\n";
152                 for my $key (sort keys %commands) {
153                         next unless defined $commands{$key}->description;
154                         my $name = sprintf "%-15s", $key;
155                         my $description = $commands{$key}->description;
156                         print_format "  <|BOLD $name|> # $description\n";
157                 }
158                 exit 0;
159         } elsif (!$commands{$command}) {
160                 print_error "no command called <|BOLD $command|> exists!",
161                         "See <|BOLD $0 help|> for a list of commands.";
162         } else {
163                 return $commands{$command}->callback->(@_);
164         }
165 }
166
167 1;