Statistics
| Branch: | Tag: | Revision:

root / kamaki / cli / commands / history_cli.py @ 439826ec

History | View | Annotate | Download (6.9 kB)

1 73e0914d Stavros Sachtouris
#!/usr/bin/env python
2 73e0914d Stavros Sachtouris
3 73e0914d Stavros Sachtouris
# Copyright 2012 GRNET S.A. All rights reserved.
4 73e0914d Stavros Sachtouris
#
5 73e0914d Stavros Sachtouris
# Redistribution and use in source and binary forms, with or
6 73e0914d Stavros Sachtouris
# without modification, are permitted provided that the following
7 73e0914d Stavros Sachtouris
# conditions are met:
8 73e0914d Stavros Sachtouris
#
9 73e0914d Stavros Sachtouris
#   1. Redistributions of source code must retain the above
10 73e0914d Stavros Sachtouris
#      copyright notice, this list of conditions and the following
11 73e0914d Stavros Sachtouris
#      disclaimer.
12 73e0914d Stavros Sachtouris
#
13 73e0914d Stavros Sachtouris
#   2. Redistributions in binary form must reproduce the above
14 73e0914d Stavros Sachtouris
#      copyright notice, this list of conditions and the following
15 73e0914d Stavros Sachtouris
#      disclaimer in the documentation and/or other materials
16 73e0914d Stavros Sachtouris
#      provided with the distribution.
17 73e0914d Stavros Sachtouris
#
18 73e0914d Stavros Sachtouris
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
19 73e0914d Stavros Sachtouris
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 73e0914d Stavros Sachtouris
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21 73e0914d Stavros Sachtouris
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
22 73e0914d Stavros Sachtouris
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 73e0914d Stavros Sachtouris
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 73e0914d Stavros Sachtouris
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
25 73e0914d Stavros Sachtouris
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
26 73e0914d Stavros Sachtouris
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 73e0914d Stavros Sachtouris
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
28 73e0914d Stavros Sachtouris
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 73e0914d Stavros Sachtouris
# POSSIBILITY OF SUCH DAMAGE.
30 73e0914d Stavros Sachtouris
#
31 73e0914d Stavros Sachtouris
# The views and conclusions contained in the software and
32 73e0914d Stavros Sachtouris
# documentation are those of the authors and should not be
33 73e0914d Stavros Sachtouris
# interpreted as representing official policies, either expressed
34 73e0914d Stavros Sachtouris
# or implied, of GRNET S.A.
35 73e0914d Stavros Sachtouris
36 d486baec Stavros Sachtouris
from kamaki.cli.command_tree import CommandTree
37 234954d1 Stavros Sachtouris
from kamaki.cli.argument import IntArgument, ValueArgument
38 fce93ff6 Stavros Sachtouris
from kamaki.cli.argument import ArgumentParseManager
39 73e0914d Stavros Sachtouris
from kamaki.cli.history import History
40 73e0914d Stavros Sachtouris
from kamaki.cli import command
41 03fd7ddb Stavros Sachtouris
from kamaki.cli.commands import _command_init
42 b6a99832 Stavros Sachtouris
from kamaki.cli import exec_cmd, print_error_message
43 ee9f8245 Stavros Sachtouris
from kamaki.cli.errors import CLIError, CLISyntaxError, raiseCLIError
44 fce93ff6 Stavros Sachtouris
from kamaki.cli.utils import split_input
45 fce93ff6 Stavros Sachtouris
from kamaki.clients import ClientError
46 73e0914d Stavros Sachtouris
47 234954d1 Stavros Sachtouris
48 d486baec Stavros Sachtouris
history_cmds = CommandTree('history', 'Command history')
49 db950b10 Stavros Sachtouris
_commands = [history_cmds]
50 234954d1 Stavros Sachtouris
51 234954d1 Stavros Sachtouris
52 00ef4ab6 Stavros Sachtouris
def _get_num_list(num_str):
53 00ef4ab6 Stavros Sachtouris
    if num_str.startswith('-'):
54 00ef4ab6 Stavros Sachtouris
        num1, sep, num2 = num_str[1:].partition('-')
55 00ef4ab6 Stavros Sachtouris
        num1 = '-%s' % num1
56 00ef4ab6 Stavros Sachtouris
    else:
57 00ef4ab6 Stavros Sachtouris
        num1, sep, num2 = num_str.partition('-')
58 00ef4ab6 Stavros Sachtouris
    (num1, num2) = (num1.strip(), num2.strip())
59 00ef4ab6 Stavros Sachtouris
    try:
60 00ef4ab6 Stavros Sachtouris
        num1 = (-int(num1[1:])) if num1.startswith('-') else int(num1)
61 00ef4ab6 Stavros Sachtouris
    except ValueError as e:
62 00ef4ab6 Stavros Sachtouris
        raiseCLIError(e, 'Invalid id %s' % num1)
63 00ef4ab6 Stavros Sachtouris
    if sep:
64 00ef4ab6 Stavros Sachtouris
        try:
65 00ef4ab6 Stavros Sachtouris
            num2 = (-int(num2[1:])) if num2.startswith('-') else int(num2)
66 519d8639 Stavros Sachtouris
            num2 += 1 if num2 > 0 else 0
67 00ef4ab6 Stavros Sachtouris
        except ValueError as e:
68 00ef4ab6 Stavros Sachtouris
            raiseCLIError(e, 'Invalid id %s' % num2)
69 00ef4ab6 Stavros Sachtouris
    else:
70 00ef4ab6 Stavros Sachtouris
        num2 = (1 + num1) if num1 else 0
71 00ef4ab6 Stavros Sachtouris
    return [i for i in range(num1, num2)]
72 00ef4ab6 Stavros Sachtouris
73 00ef4ab6 Stavros Sachtouris
74 5eae854d Stavros Sachtouris
class _init_history(_command_init):
75 234954d1 Stavros Sachtouris
    def main(self):
76 234954d1 Stavros Sachtouris
        self.history = History(self.config.get('history', 'file'))
77 234954d1 Stavros Sachtouris
78 73e0914d Stavros Sachtouris
79 d486baec Stavros Sachtouris
@command(history_cmds)
80 d53062bd Stavros Sachtouris
class history_show(_init_history):
81 c5bcc3e3 Stavros Sachtouris
    """Show intersession command history
82 c5bcc3e3 Stavros Sachtouris
    ---
83 439826ec Stavros Sachtouris
    - With no parameters : pick all commands in history records
84 439826ec Stavros Sachtouris
    - With:
85 439826ec Stavros Sachtouris
    .   1.  <order-id> : pick the <order-id>th command
86 439826ec Stavros Sachtouris
    .   2.  <order-id-1>-<order-id-2> : pick all commands ordered in the range
87 439826ec Stavros Sachtouris
    .       [<order-id-1> - <order-id-2>]
88 439826ec Stavros Sachtouris
    .   - the above can be mixed and repeated freely, separated by spaces
89 439826ec Stavros Sachtouris
    .       e.g. pick 2 4-7 -3
90 439826ec Stavros Sachtouris
    .   - Use negative integers to count from the end of the list, e.g.:
91 439826ec Stavros Sachtouris
    .       -2 means : the command before the last one
92 439826ec Stavros Sachtouris
    .       -2-5 means : last 2 commands + the first 5
93 439826ec Stavros Sachtouris
    .       -5--2 means : the last 5 commands except the last 2
94 c5bcc3e3 Stavros Sachtouris
    """
95 234954d1 Stavros Sachtouris
96 746bd77f Stavros Sachtouris
    arguments = dict(
97 746bd77f Stavros Sachtouris
        limit=IntArgument('number of lines to show', '-n', default=0),
98 746bd77f Stavros Sachtouris
        match=ValueArgument('show lines that match given terms', '--match')
99 746bd77f Stavros Sachtouris
    )
100 73e0914d Stavros Sachtouris
101 00ef4ab6 Stavros Sachtouris
    def main(self, *cmd_ids):
102 d53062bd Stavros Sachtouris
        super(self.__class__, self).main()
103 746bd77f Stavros Sachtouris
        ret = self.history.get(match_terms=self['match'], limit=self['limit'])
104 00ef4ab6 Stavros Sachtouris
105 00ef4ab6 Stavros Sachtouris
        if not cmd_ids:
106 00ef4ab6 Stavros Sachtouris
            print(''.join(ret))
107 00ef4ab6 Stavros Sachtouris
            return
108 00ef4ab6 Stavros Sachtouris
109 00ef4ab6 Stavros Sachtouris
        num_list = []
110 00ef4ab6 Stavros Sachtouris
        for num_str in cmd_ids:
111 00ef4ab6 Stavros Sachtouris
            num_list += _get_num_list(num_str)
112 00ef4ab6 Stavros Sachtouris
113 00ef4ab6 Stavros Sachtouris
        for cmd_id in num_list:
114 660a0dad Stavros Sachtouris
            try:
115 519d8639 Stavros Sachtouris
                cur_id = int(cmd_id)
116 519d8639 Stavros Sachtouris
                if cur_id:
117 519d8639 Stavros Sachtouris
                    print(ret[cur_id - (1 if cur_id > 0 else 0)][:-1])
118 660a0dad Stavros Sachtouris
            except IndexError as e2:
119 c5bcc3e3 Stavros Sachtouris
                print('LA %s LA' % self.__doc__)
120 660a0dad Stavros Sachtouris
                raiseCLIError(e2, 'Command id out of 1-%s range' % len(ret))
121 73e0914d Stavros Sachtouris
122 73e0914d Stavros Sachtouris
123 d486baec Stavros Sachtouris
@command(history_cmds)
124 73e0914d Stavros Sachtouris
class history_clean(_init_history):
125 c5bcc3e3 Stavros Sachtouris
    """Clean up history (permanent)"""
126 73e0914d Stavros Sachtouris
127 234954d1 Stavros Sachtouris
    def main(self):
128 d53062bd Stavros Sachtouris
        super(self.__class__, self).main()
129 234954d1 Stavros Sachtouris
        self.history.clean()
130 304c90b5 Stavros Sachtouris
131 33b3595a Stavros Sachtouris
132 304c90b5 Stavros Sachtouris
@command(history_cmds)
133 519d8639 Stavros Sachtouris
class history_run(_init_history):
134 68ab0942 Stavros Sachtouris
    """Run previously executed command(s)
135 c5bcc3e3 Stavros Sachtouris
    Use with:
136 439826ec Stavros Sachtouris
    .   1.  <order-id> : pick the <order-id>th command
137 439826ec Stavros Sachtouris
    .   2.  <order-id-1>-<order-id-2> : pick all commands ordered in the range
138 439826ec Stavros Sachtouris
    .       [<order-id-1> - <order-id-2>]
139 439826ec Stavros Sachtouris
    .   - Use negative integers to count from the end of the list, e.g.:
140 439826ec Stavros Sachtouris
    .       -2 means : the command before the last one
141 439826ec Stavros Sachtouris
    .       -2-5 means : last 2 commands + the first 5
142 439826ec Stavros Sachtouris
    .       -5--2 mean
143 439826ec Stavros Sachtouris
    .   - to find order ids for commands try   /history show.
144 68ab0942 Stavros Sachtouris
    """
145 304c90b5 Stavros Sachtouris
146 33b3595a Stavros Sachtouris
    _cmd_tree = None
147 33b3595a Stavros Sachtouris
148 33b3595a Stavros Sachtouris
    def __init__(self, arguments={}, cmd_tree=None):
149 33b3595a Stavros Sachtouris
        super(self.__class__, self).__init__(arguments)
150 33b3595a Stavros Sachtouris
        self._cmd_tree = cmd_tree
151 33b3595a Stavros Sachtouris
152 fce93ff6 Stavros Sachtouris
    def _run_from_line(self, line):
153 fce93ff6 Stavros Sachtouris
        terms = split_input(line)
154 fce93ff6 Stavros Sachtouris
        cmd, args = self._cmd_tree.find_best_match(terms)
155 fce93ff6 Stavros Sachtouris
        if not cmd.is_command:
156 fce93ff6 Stavros Sachtouris
            return
157 fce93ff6 Stavros Sachtouris
        try:
158 fce93ff6 Stavros Sachtouris
            instance = cmd.get_class()(self.arguments)
159 fce93ff6 Stavros Sachtouris
            instance.config = self.config
160 fce93ff6 Stavros Sachtouris
            prs = ArgumentParseManager(cmd.path.split(),
161 fce93ff6 Stavros Sachtouris
                dict(instance.arguments))
162 fce93ff6 Stavros Sachtouris
            prs.syntax = '%s %s' % (cmd.path.replace('_', ' '),
163 fce93ff6 Stavros Sachtouris
                cmd.get_class().syntax)
164 fce93ff6 Stavros Sachtouris
            prs.parse(args)
165 b6a99832 Stavros Sachtouris
            exec_cmd(instance, prs.unparsed, prs.parser.print_help)
166 fce93ff6 Stavros Sachtouris
        except (CLIError, ClientError) as err:
167 b6a99832 Stavros Sachtouris
            print_error_message(err)
168 fce93ff6 Stavros Sachtouris
        except Exception as e:
169 fce93ff6 Stavros Sachtouris
            print('Execution of [ %s ] failed' % line)
170 fce93ff6 Stavros Sachtouris
            print('\t%s' % e)
171 fce93ff6 Stavros Sachtouris
172 f2e2663e Stavros Sachtouris
    def _get_cmd_ids(self, cmd_ids):
173 ee9f8245 Stavros Sachtouris
        if not cmd_ids:
174 c5bcc3e3 Stavros Sachtouris
            raise CLISyntaxError('Usage: <id1|id1-id2> [id3|id3-id4] ...',
175 c5bcc3e3 Stavros Sachtouris
                details=self.__doc__.split('\n'))
176 f2e2663e Stavros Sachtouris
        cmd_id_list = []
177 f2e2663e Stavros Sachtouris
        for cmd_str in cmd_ids:
178 00ef4ab6 Stavros Sachtouris
            cmd_id_list += _get_num_list(cmd_str)
179 f2e2663e Stavros Sachtouris
        return cmd_id_list
180 f2e2663e Stavros Sachtouris
181 f2e2663e Stavros Sachtouris
    def main(self, *command_ids):
182 304c90b5 Stavros Sachtouris
        super(self.__class__, self).main()
183 f2e2663e Stavros Sachtouris
        cmd_list = self._get_cmd_ids(command_ids)
184 f2e2663e Stavros Sachtouris
        for cmd_id in cmd_list:
185 f2e2663e Stavros Sachtouris
            r = self.history.retrieve(cmd_id)
186 00ef4ab6 Stavros Sachtouris
            try:
187 00ef4ab6 Stavros Sachtouris
                print('< %s >' % r[:-1])
188 00ef4ab6 Stavros Sachtouris
            except (TypeError, KeyError):
189 519d8639 Stavros Sachtouris
                continue
190 f2e2663e Stavros Sachtouris
            if self._cmd_tree:
191 f2e2663e Stavros Sachtouris
                r = r[len('kamaki '):-1] if r.startswith('kamaki ') else r[:-1]
192 f2e2663e Stavros Sachtouris
                self._run_from_line(r)