Index: /LATMOS-Accounts/lib/LATMOS/Accounts/Cli.pm
===================================================================
--- /LATMOS-Accounts/lib/LATMOS/Accounts/Cli.pm	(revision 846)
+++ /LATMOS-Accounts/lib/LATMOS/Accounts/Cli.pm	(revision 847)
@@ -4,4 +4,5 @@
 use warnings;
 use LATMOS::Accounts::Log;
+use LATMOS::Accounts::Utils;
 use Term::ReadLine;
 use Text::ParseWords;
@@ -17,6 +18,6 @@
             help => 'ls object_type - list object of type object_type', 
             completion => sub {
-                if(!$_[3]) {
-                    return grep { /^\Q$_[1]\E/ } $_[0]->base->list_supported_objects
+                if(!$_[2]) {
+                    return $_[0]->base->list_supported_objects
                 } else { () }
             },
@@ -29,4 +30,23 @@
             },
         });
+    $env->add_func('search', {
+            help => 'search objecttype filter1 [filter2...] - search object according filter',
+            completion => sub {
+                if(!$_[2]) {
+                    return $_[0]->base->list_supported_objects
+                } else { return() }
+            },
+            code => sub {
+                my ($env, @args) = @_;
+                if ($_[1]) {
+                    my @res = $env->base->search_objects(@args);
+                    print $OUT map { "$_\n" } @res;
+                    $env->{_lastsearch} = \@res;
+                    $env->{_lastsearchtype} = $args[0];
+                } else {
+                    print $OUT "Object type missing";
+                }
+            },
+        });
     $env->add_func('select', {
             help => 'select object_type - select objects to perform action on it',
@@ -35,5 +55,5 @@
                     return $_[0]->base->list_objects($_[2]);
                 } else {
-                    return $_[0]->base->list_supported_objects;
+                    return '@', $_[0]->base->list_supported_objects;
                 }
             },
@@ -41,4 +61,13 @@
                 my ($env, $otype, @ids) = @_;
                 my @objs;
+                if ($otype eq '@') {
+                    if (@{$env->{_lastsearch}}) {
+                        $otype = $env->{_lastsearchtype};
+                        @ids = @{$env->{_lastsearch}};
+                    } else {
+                        print $OUT "No results store from previous search";
+                        return;
+                    }
+                }
                 if (!@ids) {
                     print $OUT 'not enough arguments';
@@ -96,12 +125,42 @@
         },
     });
+    $objenv->add_func('unset', {
+        help => 'unset attribute - unset specified attribute',
+        code => sub {
+            my ($env, $attr) = @_;
+            $attr or do {
+                print $OUT "Attributes must be specified";
+                return;
+            };
+            foreach (@{$env->{_objects}}) {
+                defined $_->set_c_fields($attr => undef) or do {
+                    print $OUT "cannot unset attributes $attr for " . $_->id;
+                    return;
+                };
+            }
+            $env->base->commit;
+            print $OUT "Changes applied";
+        },
+        completion => sub {
+            my ($env, $lastw, @args) = @_;
+            if (!$args[0]) {
+                return $env->base->list_canonical_fields($env->{_otype}, 'w')
+            }
+        },
+    });
     $objenv->add_func('set', {
         help => 'set attribute value - set an attributes to single value "value"',
         code => sub {
-            my ($env, $attr, $value) = @_;
+            my ($env, $attr, @value) = @_;
+            @value or do {
+                print $OUT "attribute and value must be specified";
+                return;
+            };
             foreach (@{$env->{_objects}}) {
-                defined $_->set_c_fields($attr => $value) or do {
+                defined $_->set_c_fields($attr => @value <= 1 ? $value[0] :
+                    \@value) or do {
                     $_->base->rollback;
-                    print $OUT "Cannot set $attr to $value for " . $_->id;
+                    printf $OUT "Cannot set $attr to %s for %s", join(', ',
+                        @value), $_->id;
                     return;
                 };
@@ -115,4 +174,7 @@
                 return $env->base->list_canonical_fields($env->{_otype}, 'w')
             } else {
+                if ($env->base->obj_attr_allowed_values($env->{_otype}, $args[0])) {
+                    return $env->base->obj_attr_allowed_values($env->{_otype}, $args[0])
+                }
                 for ($args[0]) {
                     /^manager|managedBy$/ and return
@@ -120,4 +182,6 @@
                     /^department$/ and return
                         $env->base->search_objects('group', 'sutype=dpmt');
+                    /^contratType$/ and return
+                        $env->base->search_objects('group', 'sutype=contrattype');
                     if (@{$env->{_objects}} == 1) {
                         return $env->{_objects}[0]->get_attributes($args[0]);
@@ -127,4 +191,56 @@
         },
     });
+    $objenv->add_func('list', {
+        help => 'list current selected objects',
+        code => sub {
+            printf $OUT "%s: %s", $_[0]->{_otype}, join(', ', map { $_->id }
+            @{$_[0]->{_objects}});
+        }
+    });
+    $objenv->add_func('edit', {
+            help => 'edit [object] - edit selected object using vi',
+            completion => sub {
+                return map { $_->id } @{$_[0]->{_objects}}
+            },
+            code => sub {
+                my ($env, $id) = @_;
+                my $obj;
+                if ($id) {
+                    $obj = grep { $_->id = $id } @{$env->{_objects}} or do {
+                        print $OUT "$id is not part of selected objects";
+                        return;
+                    };
+                } elsif (@{$env->{_objects}} == 1) {
+                    $obj = $env->{_objects}[0]
+                } else {
+                    print $OUT "multiple objects selected but can edit only one,"
+                    . "please specify which one";
+                    return;
+                }
+                my $res = LATMOS::Accounts::Utils::dump_read_temp_file(
+                    sub {
+                        my ($fh) = @_;
+                        $obj->text_dump($fh,
+                            {
+                                empty_attr => 1,
+                                only_rw => 1,
+                            }
+                        );
+                    },
+                    sub {
+                        my ($fh) = @_;
+                        my %attr = LATMOS::Accounts::Utils::parse_obj_file($fh);
+                        my $res = $obj->set_c_fields(%attr);
+                        if ($res) {
+                            print $OUT "Changes applied";
+                            $env->base->commit;
+                        }
+                        else { print $OUT "Error applying changes" }
+                        return $res ? 1 : 0;
+                    }
+                );
+            },
+        });
+
     if (lc($otype) eq 'user') {
         $objenv->add_func('group', {
@@ -200,5 +316,4 @@
 }
 
-
 sub new {
     my ($class, $env, $labase) = @_;
@@ -207,4 +322,6 @@
     $env->add_func('quit', { help => 'quit - exit the tool',
             code => sub { print "\n"; exit(0) }, });
+    $env->add_func('exit', { help => "exit current mode",
+            code => sub { return "EXIT" }, });
     $env;
 }
@@ -219,6 +336,7 @@
         };
         defined (my $line = $term->readline($self->prompt)) or return;
-        $self->run(shellwords($line));
+        my $res = $self->run(shellwords($line));
         $self->base->rollback;
+        if ($res && $res eq 'EXIT') { return }
     }
 }
