Pass Hooke instance to CommandEngine.run(), not UserInterface.run().
authorW. Trevor King <wking@drexel.edu>
Mon, 10 May 2010 16:43:05 +0000 (12:43 -0400)
committerW. Trevor King <wking@drexel.edu>
Mon, 10 May 2010 16:43:05 +0000 (12:43 -0400)
User interface just needs its configuration (already setup in
  Hooke.load_ui() -> ui.load_ui(self.config)
) and a read-only list of commands.  Giving the Hooke instance to
CommandEngine allows the commands to work on the Hooke instance
directly.  This makes user interfaces less intelligent (i.e. easier to
write), and more consistent (because they all depend on the same
commands engine.)

hooke/command.py
hooke/engine.py
hooke/hooke.py
hooke/hooke_cli.py
hooke/plugin/cut.py
hooke/plugin/playlist.py
hooke/ui/commandline.py

index adb38185aa9c363d89935cc3e44987023961a4f9..c044c0682135271bda016d921e83138aa6bb0088 100644 (file)
@@ -52,7 +52,7 @@ class Command (object):
             ] + arguments
         self._help = help
 
-    def run(self, inqueue=None, outqueue=None, **kwargs):
+    def run(self, hooke, inqueue=None, outqueue=None, **kwargs):
         """`Normalize inputs and handle <Argument help> before punting
         to :meth:`_run`.
         """
@@ -61,11 +61,11 @@ class Command (object):
         if outqueue == None:
             outqueue = NullQueue()
         try:
-            params = self.handle_arguments(inqueue, outqueue, kwargs)
+            params = self.handle_arguments(hooke, inqueue, outqueue, kwargs)
             if params['help'] == True:
                 outqueue.put(self.help())
                 raise(Success())
-            self._run(inqueue, outqueue, params)
+            self._run(hooke, inqueue, outqueue, params)
         except CommandExit, e:
             if isinstance(e, Failure):
                 outqueue.put(str(e))
@@ -84,7 +84,7 @@ class Command (object):
         """
         pass
 
-    def handle_arguments(self, inqueue, outqueue, params):
+    def handle_arguments(self, hooke, inqueue, outqueue, params):
         """Normalize and validate input parameters (:class:`Argument` values).
         """
         for argument in self.arguments:
@@ -108,7 +108,7 @@ class Command (object):
                 params[argument.name] = value
             if argument.callback != None:
                 if num_provided > 0:
-                    value = argument.callback(self, argument, value)
+                    value = argument.callback(hooke, self, argument, value)
                 params[argument.name] = value
             argument.validate(value)
         return params
@@ -180,7 +180,7 @@ class Argument (object):
 class StoreValue (object):
     def __init__(self, value):
         self.value = value
-    def __call__(self, command, argument, fragment=None):
+    def __call__(self, hooke, command, argument, fragment=None):
         return self.value
 
 class NullQueue (queue.Queue):
index a03a2a4228ba3b4fafbf8d75ecbfb7e0a5ba8dce..c70ee6b444ceb2d948bd46fb864528cc4c95af45 100644 (file)
@@ -5,7 +5,7 @@
 from .ui import CloseEngine, CommandMessage
 
 class CommandEngine (object):
-    def run(self, ui_to_command_queue, command_to_ui_queue):
+    def run(self, hooke, ui_to_command_queue, command_to_ui_queue):
         """Get a :class:`hooke.ui.QueueMessage` from the incoming
         `ui_to_command_queue` and act accordingly.
 
@@ -24,5 +24,5 @@ class CommandEngine (object):
             if isinstance(msg, CloseEngine):
                 break
             assert isinstance(msg, CommandMessage), type(msg)
-            msg.command.run(ui_to_command_queue, command_to_ui_queue,
+            msg.command.run(hooke, ui_to_command_queue, command_to_ui_queue,
                             **msg.arguments)
index 0b05aff1cbb6d3952c05d5ee66a3bddfee9e1e34..4142a5f2a4ff5385ea09e369805990a9b88ecf60 100644 (file)
@@ -12,6 +12,7 @@ import multiprocessing
 
 from . import engine as engine
 from . import config as config_mod
+from . import playlist as playlist
 from . import plugin as plugin_mod
 from . import driver as driver_mod
 from . import ui as ui
@@ -34,6 +35,8 @@ class Hooke (object):
         self.load_ui()
         self.command = engine.CommandEngine()
 
+        self.playlists = playlist.PlaylistManager()
+
     def load_plugins(self):
         self.plugins = plugin_mod.load_graph(
             plugin_mod.PLUGIN_GRAPH, self.config, include_section='plugins')
@@ -61,10 +64,10 @@ class Hooke (object):
         ui_to_command = multiprocessing.Queue()
         command_to_ui = multiprocessing.Queue()
         command = multiprocessing.Process(
-            target=self.command.run, args=(ui_to_command, command_to_ui))
+            target=self.command.run, args=(self, ui_to_command, command_to_ui))
         command.start()
         try:
-            self.ui.run(self, ui_to_command, command_to_ui)
+            self.ui.run(self.commands, ui_to_command, command_to_ui)
         finally:
             ui_to_command.put(ui.CloseEngine())
             command.join()
index 2bd9628019448f65361f8c7ea172f3e87a1b18b2..bbb6cc69e31176ac0aa4bc1e37fcac214e72eda3 100644 (file)
@@ -206,166 +206,6 @@ Syntax: set [variable] [value]
         self.config[key]=value
         self.do_plot(0)
 
-#PLAYLIST MANAGEMENT AND NAVIGATION
-#------------------------------------
-
-    def help_loadlist(self):
-        print '''
-LOADLIST
-Loads a file playlist
------------
-Syntax: loadlist [playlist file]
-        '''
-    def do_loadlist(self, args):
-        #checking for args: if nothing is given as input, we warn and exit.
-        while len(args)==0:
-            args=linp.safeinput('File to load?')
-
-        arglist=args.split()
-        play_to_load=arglist[0]
-
-        #We assume a Hooke playlist has the extension .hkp
-        if play_to_load[-4:] != '.hkp':
-            play_to_load+='.hkp'
-
-        try:
-            playxml=PlaylistXML()
-            self.current_list, self.playlist_generics=playxml.load(play_to_load)
-            self.current_playxml=playxml
-        except IOError:
-            print 'File not found.', play_to_load
-            return
-
-        print 'Loaded %s curves from %s' \
-            % (len(self.current_list), play_to_load)
-
-        if 'pointer' in self.playlist_generics.keys():
-            self.pointer=int(self.playlist_generics['pointer'])
-        else:
-            #if no pointer is found, set the current curve as the first curve of the loaded playlist
-            self.pointer=0
-        print 'Starting at curve ',self.pointer
-
-        self.current=self.current_list[self.pointer]
-
-        #resets saved/notes saved state
-        self.playlist_saved=0
-        self.playlist_name=''
-        self.notes_saved=0
-
-        self.do_plot(0)
-
-
-    def help_genlist(self):
-        print '''
-GENLIST
-Generates a file playlist.
-Note it doesn't *save* it: see savelist for this.
-
-If [input files] is a directory, it will use all files in the directory for playlist.
-So:
-genlist dir
-genlist dir/
-genlist dir/*.*
-
-are all equivalent syntax.
-------------
-Syntax: genlist [input files]
-
-'''
-    def do_genlist(self,args):
-        #args list is: input path, output name
-        if len(args)==0:
-            args=linp.safeinput('Input files?')
-
-        arglist=args.split()
-        list_path=arglist[0]
-
-        #if it's a directory, is like /directory/*.*
-        #FIXME: probably a bit kludgy.
-        if os.path.isdir(list_path):
-            if platform.system == 'Windows':
-                SLASH="\\"
-            else:
-                SLASH="/"
-            if list_path[-1] == SLASH:
-                list_path=list_path+'*'
-            else:    
-                list_path=list_path+SLASH+'*'
-        
-        #expanding correctly the input list with the glob module :)        
-        list_files=glob.glob(list_path)
-        list_files.sort()
-
-        self.current_list=[]
-        for item in list_files:
-            try:
-                if os.path.isfile(item):
-                    self.current_list.append(lhc.HookeCurve(os.path.abspath(item)))
-            except:
-                pass
-
-        self.pointer=0
-        if len(self.current_list)>0:
-            self.current=self.current_list[self.pointer]
-        else:
-            print 'Empty list!'
-            return
-
-        #resets saved/notes saved state
-        self.playlist_saved=0
-        self.playlist_name=''
-        self.notes_saved=0
-
-        self.do_plot(0)
-
-
-    def do_savelist(self,args):
-        '''
-        SAVELIST
-        Saves the current file playlist on disk.
-        ------------
-        Syntax: savelist [filename]
-        '''
-        while len(args)==0:
-            args=linp.safeinput('Output file?',['savedlist.txt'])
-
-        output_filename=args
-
-        self.playlist_generics['pointer']=self.pointer
-
-        #autocomplete filename if not specified
-        if output_filename[-4:] != '.hkp':
-            output_filename+='.hkp'
-
-        playxml=PlaylistXML()
-        playxml.export(self.current_list, self.playlist_generics)
-        playxml.save(output_filename)
-
-        #remembers we have saved playlist
-        self.playlist_saved=1
-
-    def help_addtolist(self):
-        print '''
-ADDTOLIST
-Adds a file to the current playlist
---------------
-Syntax: addtolist [filename]
-'''
-    def do_addtolist(self,args):
-        #args list is: input path
-        if len(args)==0:
-            print 'You must give the input filename you want to add'
-            self.help_addtolist()
-            return
-
-        filenames=glob.glob(args)
-
-        for filename in filenames:
-            self.current_list.append(lhc.HookeCurve(os.path.abspath(filename)))
-        #we need to save playlist
-        self.playlist_saved=0
-
     def help_printlist(self):
         print '''
 PRINTLIST
index e93367bd122cbbfa0742f4c9d3aea0f48efb8934..dc55d89161a719e27bb81d8076d2186c2a4420bd 100644 (file)
@@ -22,8 +22,8 @@ class CutCommand (Command):
         super(CutCommand, self).__init__(
             name='cut',
             arguments=[
-                Argument(name='curve', type='curve', optional=False, help="""
-:class:`hooke.curve.Curve` to cut from.
+                Argument(name='curve', type='curve', help="""
+:class:`hooke.curve.Curve` to cut from.  Defaults to the current curve.
 """.strip()),
                 Argument(name='block', aliases=['set'], type='int', default=0,
                     help="""
@@ -41,7 +41,10 @@ File name for the output data.
                 ],
             help=self.__doc__)
 
-    def _run(self, inqueue, outqueue, params):
+    def _run(self, hooke, inqueue, outqueue, params):
+        if params['curve'] == None:
+            params['curve'] = hooke.playlists.current().current()
+
        i_min = min([p.index for p in params['points']])
        i_max = max([p.index for p in params['points']])
 
index 04116b7f1ced099964fc64aa0eab41a1afde8c34..8d0559c91c613544c988ea55c0e1648d714dd125 100644 (file)
@@ -20,21 +20,40 @@ class PlaylistPlugin (Builtin):
                 AddCommand(), AddGlobCommand(),
                 RemoveCommand(), FilterCommand()]
 
+# Define common or complicated arguments
+
+def current_playlist_callback(hooke, command, argument, value):
+    return hooke.playlists.current()
+
+PlaylistArgument = Argument(
+    name='playlist', type='playlist', callback=current_playlist_callback,
+    help="""
+:class:`hooke.plugin.playlist.Playlist` to act on.  Defaults to the
+current playlist.
+""".strip()),
+
+def playlist_name_callback(hooke, command, argument, value):
+        return hooke.playlists.free_name()
+
+PlaylistNameArgument = Argument(
+    name='name', type='string', optional=True, callback=playlist_name_callback,
+    help="""
+Name of the new playlist (defaults to an auto-generated name).
+""".strip())
+
+
+# Define commands
+
 class NextCommand (Command):
     """Move playlist to the next curve.
     """
     def __init__(self):
         super(NextCommand, self).__init__(
             name='next curve',
-            arguments=[
-                Argument(name='playlist', type='playlist', optional=False,
-                         help="""
-:class:`hooke.plugin.playlist.Playlist` to act on.
-""".strip()),
-                ],
+            arguments=[PlaylistArgument],
             help=self.__doc__)
 
-    def _run(self, inqueue, outqueue, params):
+    def _run(self, hooke, inqueue, outqueue, params):
        params['playlist'].next()
 
 class PreviousCommand (Command):
@@ -43,15 +62,10 @@ class PreviousCommand (Command):
     def __init__(self):
         super(PreviousCommand, self).__init__(
             name='previous curve',
-            arguments=[
-                Argument(name='playlist', type='playlist', optional=False,
-                         help="""
-:class:`hooke.plugin.playlist.Playlist` to act on.
-""".strip()),
-                ],
+            arguments=[PlaylistArgument],
             help=self.__doc__)
 
-    def _run(self, inqueue, outqueue, params):
+    def _run(self, hooke, inqueue, outqueue, params):
        params['playlist'].previous()
 
 class JumpCommand (Command):
@@ -61,17 +75,14 @@ class JumpCommand (Command):
         super(JumpCommand, self).__init__(
             name='jump to curve',
             arguments=[
-                Argument(name='playlist', type='playlist', optional=False,
-                         help="""
-:class:`hooke.plugin.playlist.Playlist` to act on.
-""".strip()),
+                PlaylistArgument,
                 Argument(name='index', type='int', optional=False, help="""
 Index of target curve.
 """.strip()),
                 ],
             help=self.__doc__)
 
-    def _run(self, inqueue, outqueue, params):
+    def _run(self, hooke, inqueue, outqueue, params):
        params['playlist'].jump(params['index'])
 
 class SaveCommand (Command):
@@ -81,19 +92,16 @@ class SaveCommand (Command):
         super(SaveCommand, self).__init__(
             name='save playlist',
             arguments=[
-                Argument(name='playlist', type='playlist', optional=False,
-                         help="""
-:class:`hooke.plugin.playlist.Playlist` to act on.
-""".strip()),
+                PlaylistArgument,
                 Argument(name='output', type='file',
                          help="""
-File name for the output playlist.  Defaults to overwring the input
+File name for the output playlist.  Defaults to overwriting the input
 playlist.
 """.strip()),
                 ],
             help=self.__doc__)
 
-    def _run(self, inqueue, outqueue, params):
+    def _run(self, hooke, inqueue, outqueue, params):
        params['playlist'].save(params['output'])
 
 class LoadCommand (Command):
@@ -107,17 +115,18 @@ class LoadCommand (Command):
                          help="""
 File name for the input playlist.
 """.strip()),
-                Argument(name='digests', type='digest', optional=False,
+                Argument(name='drivers', type='driver', optional=False,
                          count=-1,
                          help="""
-Digests for loading curves.
+Drivers for loading curves.
 """.strip()),
                 ],
             help=self.__doc__)
 
-    def _run(self, inqueue, outqueue, params):
+    def _run(self, hooke, inqueue, outqueue, params):
         p = FilePlaylist(drivers=params['drivers'], path=params['input'])
         p.load()
+        hooke.playlists.append(p)
        outqueue.put(p)
 
 class AddCommand (Command):
@@ -127,10 +136,7 @@ class AddCommand (Command):
         super(AddCommand, self).__init__(
             name='add curve to playlist',
             arguments=[
-                Argument(name='playlist', type='playlist', optional=False,
-                         help="""
-:class:`hooke.plugin.playlist.Playlist` to act on.
-""".strip()),
+                PlaylistArgument,
                 Argument(name='input', type='file', optional=False,
                          help="""
 File name for the input :class:`hooke.curve.Curve`.
@@ -142,7 +148,7 @@ Additional information for the input :class:`hooke.curve.Curve`.
                 ],
             help=self.__doc__)
 
-    def _run(self, inqueue, outqueue, params):
+    def _run(self, hooke, inqueue, outqueue, params):
         params['playlist'].append_curve_by_path(params['input'],
                                                 params['info'])
 
@@ -157,10 +163,7 @@ class AddGlobCommand (Command):
         super(AddGlobCommand, self).__init__(
             name='glob curves to playlist',
             arguments=[
-                Argument(name='playlist', type='playlist', optional=False,
-                         help="""
-:class:`hooke.plugin.playlist.Playlist` to act on.
-""".strip()),
+                PlaylistArgument,
                 Argument(name='input', type='glob', optional=False,
                          help="""
 File name glob for the input :class:`hooke.curve.Curve`.
@@ -172,7 +175,7 @@ Additional information for the input :class:`hooke.curve.Curve`.
                 ],
             help=self.__doc__)
 
-    def _run(self, inqueue, outqueue, params):
+    def _run(self, hooke, inqueue, outqueue, params):
         for path in sorted(glob.glob(params['input'])):
             params['playlist'].append_curve_by_path(path, params['info'])
 
@@ -183,17 +186,14 @@ class RemoveCommand (Command):
         super(RemoveCommand, self).__init__(
             name='remove curve from playlist',
             arguments=[
-                Argument(name='playlist', type='playlist', optional=False,
-                         help="""
-:class:`hooke.plugin.playlist.Playlist` to act on.
-""".strip()),
+                PlaylistArgument,
                 Argument(name='index', type='int', optional=False, help="""
 Index of target curve.
 """.strip()),
                 ],
             help=self.__doc__)
 
-    def _run(self, inqueue, outqueue, params):
+    def _run(self, hooke, inqueue, outqueue, params):
         params['playlist'].pop(params['index'])
         params['playlist'].jump(params._index)
 
@@ -208,10 +208,8 @@ class FilterCommand (Command):
         super(FilterCommand, self).__init__(
             name='filter playlist',
             arguments=[
-                Argument(name='playlist', type='playlist', optional=False,
-                         help="""
-:class:`hooke.plugin.playlist.Playlist` to act on.
-""".strip()),
+                PlaylistArgument,
+                PlaylistNameArgument,
                 Argument(name='filter', type='function', optional=False,
                          help="""
 Function returning `True` for "good" curves.  `filter(curve) -> True/False`.
@@ -219,6 +217,7 @@ Function returning `True` for "good" curves.  `filter(curve) -> True/False`.
                 ],
             help=self.__doc__)
 
-    def _run(self, inqueue, outqueue, params):
+    def _run(self, hooke, inqueue, outqueue, params):
         p = params['playlist'].filter(params['filter'])
+        hooke.playlists.add(p)
         outqueue.put(p)
index c9ed605fb07b234d15b50c2a8da054ad470d082e..41fe990a436ff84dc3b50280534dac815912e82e 100644 (file)
@@ -98,9 +98,9 @@ class CompleteCommand (CommandMethod):
 # Now onto the main attraction.
 
 class HookeCmd (cmd.Cmd):
-    def __init__(self, hooke, inqueue, outqueue):
+    def __init__(self, commands, inqueue, outqueue):
         cmd.Cmd.__init__(self)
-        self.hooke = hooke
+        self.commands = commands
         self.prompt = 'hooke> '
         self._add_command_methods()
         self.inqueue = inqueue
@@ -110,7 +110,7 @@ class HookeCmd (cmd.Cmd):
         return name.lower().replace(' ', '_')
 
     def _add_command_methods(self):
-        for command in self.hooke.commands:
+        for command in self.commands:
             command.name = self._safe_name(command.name)
             command.aliases = [self._safe_name(n) for n in command.aliases]
             for name in [command.name] + command.aliases: