Moved printlist command from hooke_cli -> hooke.plugin.playlist.CurveListCommand.
[hooke.git] / hooke / plugin / playlist.py
1 """The `playlist` module provides :class:`PlaylistPlugin` several
2 associated :class:`hooke.command.Command`\s for handling
3 :mod:`hooke.playlist` classes.
4 """
5
6 import glob
7
8 from ..command import Command, Argument, Failure
9 from ..playlist import FilePlaylist
10 from ..plugin import Builtin
11
12
13 class PlaylistPlugin (Builtin):
14     def __init__(self):
15         super(PlaylistPlugin, self).__init__(name='playlist')
16
17     def commands(self):
18         return [NextCommand(), PreviousCommand(), JumpCommand(),
19                 IndexCommand(), CurveListCommand(),
20                 SaveCommand(), LoadCommand(),
21                 AddCommand(), AddGlobCommand(),
22                 RemoveCommand(), FilterCommand(), NoteFilterCommand()]
23
24
25 # Define common or complicated arguments
26
27 def current_playlist_callback(hooke, command, argument, value):
28     if value != None:
29         return value
30     playlist = hooke.playlists.current()
31     if playlist == None:
32         raise Failure('No playlists loaded')
33     return playlist
34
35 PlaylistArgument = Argument(
36     name='playlist', type='playlist', callback=current_playlist_callback,
37     help="""
38 :class:`hooke.plugin.playlist.Playlist` to act on.  Defaults to the
39 current playlist.
40 """.strip())
41
42 def playlist_name_callback(hooke, command, argument, value):
43         return hooke.playlists.free_name()
44
45 PlaylistNameArgument = Argument(
46     name='name', type='string', optional=True, callback=playlist_name_callback,
47     help="""
48 Name of the new playlist (defaults to an auto-generated name).
49 """.strip())
50
51
52 # Define commands
53
54 class NextCommand (Command):
55     """Move playlist to the next curve.
56     """
57     def __init__(self):
58         super(NextCommand, self).__init__(
59             name='next curve',
60             arguments=[PlaylistArgument],
61             help=self.__doc__)
62
63     def _run(self, hooke, inqueue, outqueue, params):
64         params['playlist'].next()
65
66 class PreviousCommand (Command):
67     """Move playlist to the previous curve.
68     """
69     def __init__(self):
70         super(PreviousCommand, self).__init__(
71             name='previous curve',
72             arguments=[PlaylistArgument],
73             help=self.__doc__)
74
75     def _run(self, hooke, inqueue, outqueue, params):
76         params['playlist'].previous()
77
78 class JumpCommand (Command):
79     """Move playlist to a given curve.
80     """
81     def __init__(self):
82         super(JumpCommand, self).__init__(
83             name='jump to curve',
84             arguments=[
85                 PlaylistArgument,
86                 Argument(name='index', type='int', optional=False, help="""
87 Index of target curve.
88 """.strip()),
89                 ],
90             help=self.__doc__)
91
92     def _run(self, hooke, inqueue, outqueue, params):
93         params['playlist'].jump(params['index'])
94
95 class IndexCommand (Command):
96     """Print the index of the current curve.
97
98     The first curve has index 0.
99     """
100     def __init__(self):
101         super(IndexCommand, self).__init__(
102             name='curve index',
103             arguments=[
104                 PlaylistArgument,
105                 ],
106             help=self.__doc__)
107
108     def _run(self, hooke, inqueue, outqueue, params):
109         outqueue.put(params['playlist']._index)
110
111 class CurveListCommand (Command):
112     """Get the curves in a playlist.
113     """
114     def __init__(self):
115         super(CurveListCommand, self).__init__(
116             name='playlist curves',
117             arguments=[
118                 PlaylistArgument,
119                 ],
120             help=self.__doc__)
121
122     def _run(self, hooke, inqueue, outqueue, params):
123         outqueue.put([c for c in params['playlist']])
124
125 class SaveCommand (Command):
126     """Save a playlist.
127     """
128     def __init__(self):
129         super(SaveCommand, self).__init__(
130             name='save playlist',
131             arguments=[
132                 PlaylistArgument,
133                 Argument(name='output', type='file',
134                          help="""
135 File name for the output playlist.  Defaults to overwriting the input
136 playlist.
137 """.strip()),
138                 ],
139             help=self.__doc__)
140
141     def _run(self, hooke, inqueue, outqueue, params):
142         params['playlist'].save(params['output'])
143
144 class LoadCommand (Command):
145     """Load a playlist.
146     """
147     def __init__(self):
148         super(LoadCommand, self).__init__(
149             name='load playlist',
150             arguments=[
151                 Argument(name='input', type='file', optional=False,
152                          help="""
153 File name for the input playlist.
154 """.strip()),
155                 Argument(name='drivers', type='driver', optional=False,
156                          count=-1,
157                          help="""
158 Drivers for loading curves.
159 """.strip()),
160                 ],
161             help=self.__doc__)
162
163     def _run(self, hooke, inqueue, outqueue, params):
164         p = FilePlaylist(drivers=params['drivers'], path=params['input'])
165         p.load()
166         hooke.playlists.append(p)
167         outqueue.put(p)
168
169 class AddCommand (Command):
170     """Add a curve to a playlist.
171     """
172     def __init__(self):
173         super(AddCommand, self).__init__(
174             name='add curve to playlist',
175             arguments=[
176                 PlaylistArgument,
177                 Argument(name='input', type='file', optional=False,
178                          help="""
179 File name for the input :class:`hooke.curve.Curve`.
180 """.strip()),
181                 Argument(name='info', type='dict', optional=True,
182                          help="""
183 Additional information for the input :class:`hooke.curve.Curve`.
184 """.strip()),
185                 ],
186             help=self.__doc__)
187
188     def _run(self, hooke, inqueue, outqueue, params):
189         params['playlist'].append_curve_by_path(params['input'],
190                                                 params['info'])
191
192 class AddGlobCommand (Command):
193     """Add curves to a playlist with file globbing.
194
195     Adding lots of files one at a time can be tedious.  With this
196     command you can use globs (`data/curves/*.dat`) to add curves
197     for all matching files at once.
198     """
199     def __init__(self):
200         super(AddGlobCommand, self).__init__(
201             name='glob curves to playlist',
202             arguments=[
203                 PlaylistArgument,
204                 Argument(name='input', type='glob', optional=False,
205                          help="""
206 File name glob for the input :class:`hooke.curve.Curve`.
207 """.strip()),
208                 Argument(name='info', type='dict', optional=True,
209                          help="""
210 Additional information for the input :class:`hooke.curve.Curve`.
211 """.strip()),
212                 ],
213             help=self.__doc__)
214
215     def _run(self, hooke, inqueue, outqueue, params):
216         for path in sorted(glob.glob(params['input'])):
217             params['playlist'].append_curve_by_path(path, params['info'])
218
219 class RemoveCommand (Command):
220     """Remove a curve from a playlist.
221     """
222     def __init__(self):
223         super(RemoveCommand, self).__init__(
224             name='remove curve from playlist',
225             arguments=[
226                 PlaylistArgument,
227                 Argument(name='index', type='int', optional=False, help="""
228 Index of target curve.
229 """.strip()),
230                 ],
231             help=self.__doc__)
232
233     def _run(self, hooke, inqueue, outqueue, params):
234         params['playlist'].pop(params['index'])
235         params['playlist'].jump(params._index)
236
237 class FilterCommand (Command):
238     """Create a subset playlist via a selection function.
239
240     Removing lots of curves one at a time can be tedious.  With this
241     command you can use a function `filter` to select the curves you
242     wish to keep.
243     """
244     def __init__(self):
245         super(FilterCommand, self).__init__(
246             name='filter playlist',
247             arguments=[
248                 PlaylistArgument,
249                 PlaylistNameArgument,
250                 Argument(name='filter', type='function', optional=False,
251                          help="""
252 Function returning `True` for "good" curves.  `filter(curve) -> True/False`.
253 """.strip()),
254                 ],
255             help=self.__doc__)
256
257     def _run(self, hooke, inqueue, outqueue, params):
258         p = params['playlist'].filter(params['filter'])
259         hooke.playlists.add(p)
260         outqueue.put(p)
261
262 class NoteFilterCommand (FilterCommand):
263     """Create a subset playlist of curves with `.info['note'] != None`.
264     """
265     def __init__(self):
266         super(NoteFilterCommand, self).__init__()
267         self.name = 'note filter playlist'
268         self.arguments = [a for a in self.arguments if a.name != 'filter']
269
270     def _run(self, hooke, inqueue, outqueue, params):
271         params['filter'] = lambda curve : \
272             'note' in curve.info and curve.info['note'] != None
273         return super(NoteFilterCommand, self)._run(
274             hooke, inqueue, outqueue, params)