source: trunk/LATMOS-Accounts/lib/LATMOS/Accounts/Cli/Base.pm @ 2209

Last change on this file since 2209 was 2209, checked in by nanardon, 5 years ago

Rework la-cli to ease functions adding

File size: 8.4 KB
Line 
1package LATMOS::Accounts::Cli::Base;
2
3# $Id: Cli.pm 2145 2018-08-29 18:15:46Z nanardon $
4
5use strict;
6use warnings;
7use Moose;
8use LATMOS::Accounts::Cli::Context;
9use LATMOS::Accounts::Log;
10use LATMOS::Accounts::Utils;
11use Term::ReadLine;
12use Text::ParseWords;
13use Getopt::Long;
14
15=head1 NAME
16
17LATMOS::Accounts::Cli - Command line interface functions
18
19=head1 DESCRIPTION
20
21This module handle envirronment and functons for L<la-cli> tools.
22
23=cut
24
25has Context => ( is => 'ro', isa => 'LATMOS::Accounts::Cli::Context' );
26
27=head1 FUNCTIONS
28
29=cut
30
31sub BUILD {
32    my $self = shift;
33
34    my $OUT = $self->Context->Out;
35
36    if ($self->base->is_transactionnal) {
37        $self->add_func(
38            'transaction', {
39                help => 'change transaction mode',
40                code => sub {
41                    $self->Context->TransMode($_[1] eq 'on' ? 1 : 0);
42                },
43                completion => sub {
44                    $self->Context->TransMode == 0 ? 'on' : 'off';
45                },
46            }
47        );
48        $self->add_func(
49            'begin', {
50                help => 'Start transaction',
51                code => sub {
52                    $self->Context->TransStarted(1);
53                },
54            }
55        );
56        $self->add_func(
57            'commit', {
58                help => 'commit pending change',
59                code => sub {
60                    $_[0]->_commit;
61                },
62            }
63        );
64        $self->add_func(
65            'rollback', {
66                help => 'commit pending change',
67                code => sub {
68                    $_[0]->_rollback;
69                },
70            }
71        );
72    }
73    if ($self->base->can('CreateAlias')) {
74        $self->add_func(
75            'newalias', {
76                help => 'Create an alias object',
77                code => sub {
78                    my ($self, $otype, $name, $for) = @_;
79                    if ($self->base->CreateAlias($otype, $name, $for)) {
80                        print $OUT "Alias $otype/$name Created\n";
81                        $self->commit;
82                    }
83                },
84                completion => sub {
85                    if ($_[3]) {
86                        return $_[0]->base->list_objects($_[2]);
87                    } elsif (!$_[2]) {
88                        return $_[0]->base->list_supported_objects;
89                    } else {
90                        return;
91                    }
92                }
93            },
94        );
95        $self->add_func(
96            'rmalias', {
97                help => 'Remove an alias object',
98                code => sub {
99                    my ($self, $otype, $name) = @_;
100                    if ($self->base->RemoveAlias($otype, $name)) {
101                        print $OUT "Alias $otype/$name Removed\n";
102                        $self->commit;
103                    }
104                },
105                completion => sub {
106                    if (!$_[2]) {
107                        return $_[0]->base->list_supported_objects;
108                    } else {
109                        return $_[0]->base->search_objects($_[2], 'oalias=*');
110                    }
111                }
112            },
113        );
114        $self->add_func(
115            'updalias', {
116                help => 'Update an alias object',
117                code => sub {
118                    my ($self, $otype, $name, $for) = @_;
119                    my $obj = $self->base->GetAlias($otype, $name) or do {
120                        print $OUT "No alias $otype/$name found";
121                        return;
122                    };
123                    if ($obj->set_c_fields(oalias => $for)) {
124                        print $OUT "Alias $otype/$name Updated\n";
125                        $self->commit;
126                    }
127                },
128                completion => sub {
129                    if ($_[3]) {
130                        return $_[0]->base->list_objects($_[2]);
131                    } elsif($_[2]) {
132                        return $_[0]->base->search_objects($_[2], 'oalias=*');
133                    } else {
134                        return $_[0]->base->list_supported_objects;
135                    }
136                }
137            },
138        );
139    }
140    $self->add_func('quit', { help => 'quit - exit the tool',
141            code => sub { print "\n"; exit(0) }, });
142    $self->add_func('exit', { help => "exit current mode",
143            code => sub { return "EXIT" }, });
144    $self->add_func('help', {
145        help => 'help [command] - print help about command',
146        completion => sub {
147            if (!$_[2]) { return sort keys %{ $_[0]->{funcs} || {}} }
148        },
149        code => sub {
150            my ($self, $name) = @_;
151            if (!$name) {
152                print $OUT join(', ', sort keys %{ $self->{funcs} || {}}) . "\n";
153            } elsif ($self->{funcs}{$name}{alias}) {
154                print $OUT "$name is an alias for " . join(' ',
155                    @{$self->{funcs}{$name}{alias}}) . "\n";
156            } elsif ($self->{funcs}{$name}{help}) {
157                print $OUT $self->{funcs}{$name}{help} . "\n";
158            } else {
159                print $OUT "No help availlable\n";
160            }
161        },
162    });
163}
164
165=head2 base
166
167Return the attached base object.
168
169=cut
170
171sub base { $_[0]->Context->base }
172sub term { $_[0]->Context->Term }
173sub print { shift->Context->print(@_) }
174
175=head2 cli
176
177Start the main loop
178
179=cut
180
181sub cli {
182    my ($self) = @_;
183
184    my $term = $_[0]->Context->Term;
185
186    while (1) {
187        $term->Attribs->{completion_function} = sub {
188            $self->complete($_[0], shellwords(substr($_[1], 0, $_[2])));
189        };
190        defined (my $line = $term->readline($self->prompt)) or do {
191            $self->print("\n");
192            return;
193        };
194        $term->addhistory($line);
195        my $res = $self->run(shellwords($line));
196        $self->rollback if (!$self->Context->TransMode);
197        if ($res && $res eq 'EXIT') { $self->print("\n"); return }
198    }
199}
200
201=head2 prompt
202
203Wait user to input command
204
205=cut
206
207sub promptPrefix { 'LA cli' }
208
209sub prompt {
210    my ($self) = @_;
211    my $pr = $self->promptPrefix;
212    return sprintf(
213        "%s%s%s ",
214        $pr,
215        $self->Context->TransStarted ? '-' : '=',
216        $self->Context->TransMode  ? '#' : '>',
217    );
218}
219
220=head2 add_func ($name, $param)
221
222Add new function in the envirronment
223
224=cut
225
226# TODO: hide this
227
228sub add_func {
229    my ($self, $name, $param) = @_;
230    $self->{funcs}{$name} = $param;
231}
232
233=head2 getoption ($opt, @args)
234
235Parse commmand line
236
237=cut
238
239sub getoption {
240    my ($self, $opt, @args) = @_;
241    local @ARGV = @args;
242    Getopt::Long::Configure("pass_through");
243    GetOptions(%{ $opt });
244
245    return @ARGV;
246}
247
248=head2 complete
249
250Return possible words according current entered words
251
252=cut
253
254sub complete {
255    my ($self, $lastw, $name, @args) = @_;
256    if (!$name) {
257        return grep { /^\Q$lastw\E/ } sort
258            (keys %{ $self->{funcs} || {}});
259    } elsif ($self->{funcs}{$name}{alias}) {
260        $self->complete($lastw, @{$self->{funcs}{$name}{alias}}, @args);
261    } elsif ($self->{funcs}{$name}{completion}) {
262        return map { my $t = $_; $t =~ s/\s/\\ /g; $t } grep { $_ && /^\Q$lastw\E/ } $self->{funcs}{$name}{completion}->($self, $lastw, @args);
263    } else {
264        return ();
265    }
266}
267
268=head2 run ($name, @args)
269
270Run functions
271
272=cut
273
274sub run {
275    my ($self, $name, @args) = @_;
276    return if (!$name);
277    if (!exists($self->{funcs}{$name})) {
278        $self->print("No command $name found\n");
279    } elsif ($self->{funcs}{$name}{alias}) {
280        $self->run(@{$self->{funcs}{$name}{alias}}, @args);
281    } elsif ($self->{funcs}{$name}{code}) {
282        $self->{funcs}{$name}{code}->($self, @args);
283    } else {
284        $self->print("No command $name found\n");
285    }
286}
287
288=head2 commit
289
290Call commit to base unelss in transaction mode
291
292=cut
293
294sub commit {
295    my ($self) = @_;
296    $self->Context->commit;
297}
298
299sub _commit {
300    my ($self) = @_;
301    $self->Context->_commit;
302}
303
304=head2 rollback
305
306Perform rollback unless in transaction mode
307
308=cut
309
310sub rollback {
311    my ($self) = @_;
312    $self->Context->rollback;
313}
314
315sub _rollback {
316    my ($self) = @_;
317    $self->Context->_rollback;
318}
319
3201;
321
322__END__
323
324=head1 SEE ALSO
325
326L<LATMOS::Accounts>
327
328=head1 AUTHOR
329
330Olivier Thauvin, E<lt>olivier.thauvin@latmos.ipsl.frE<gt>
331
332=head1 COPYRIGHT AND LICENSE
333
334Copyright (C) 2008, 2009, 2010, 2011, 2012 CNRS SA/CETP/LATMOS
335
336This library is free software; you can redistribute it and/or modify
337it under the same terms as Perl itself, either Perl version 5.10.0 or,
338at your option, any later version of Perl 5 you may have available.
339
340=cut
Note: See TracBrowser for help on using the repository browser.