def __init__(self, c_handler=None, recorder=None, jm=None, ui=None):
        self.console_handler = c_handler
        self.record = recorder
        self.jm = jm  # JointManager from the module 'record'
        self.ui = ui
        self.helpmap = None  # Holds the help (if loading succeds)
        self.all_commands = {}  # Convinence dict holding merged commands and aliases
        self.aliases = {}  # Holds alias definitions (if loading succeds)
        self.motor_info_provider = MotorInfoProvider()
        self.commands = {
            'help': self.cmd_help,
            'quit': self.cmd_quit,
            'exit': self.cmd_quit,
            'record': self.cmd_rec_record,
            'dump': self.cmd_rec_dump,
            'load': self.cmd_rec_load,
            'play': self.cmd_rec_play,
            'clear': self.cmd_rec_clear,
            'revert': self.cmd_rec_revert,
            'init': self.cmd_rec_init,
            'append': self.cmd_rec_append,
            'on': self.cmd_jm_on,
            'off': self.cmd_jm_off,
            'loglevel': self.cmd_loglevel,
            'copy': self.cmd_rec_copy,
            'move': self.cmd_rec_move,
            'pose': self.cmd_rec_pose,
            'desc': self.cmd_rec_desc,
            'meta': self.cmd_meta,
            'author': self.cmd_rec_author,
            'motors': self.cmd_motors,
            'motorinfo': self.cmd_motorinfo,
            'mirror': self.cmd_rec_mirror,
            'id': self.cmd_id,
            'undo': self.cmd_rec_undo,
            'redo': self.cmd_rec_redo,
            'xxxtestcommand': self.cmd_xxxtestcommand
        }

        self.autocompletions = {
            'load': self.ac_anim,
            'play': self.ac_anim,
            'append': self.ac_anim
        }

        self.load_aliases()
        self.load_help()
    def __init__(self, ui_debug=False, ipc=None):
        # init logging

        # Palette maps colors to attribute specifiers
        # All UI-Elements may be assigned these attributes
        palette = self.load_palette()
        # Set Encoding to UTF-8
        # usually urwid respects the system locale
        # but it is much more likely that the locale is wrong,
        # than that we ever need other encodings than utf-8.
        urwid.set_encoding("UTF-8")
        # register signals
        urwid.register_signal(DataFieldWidget, ["field_changed"])
        urwid.register_signal(KeyframeWidget, ["frame_changed"])
        signal.signal(signal.SIGTERM, self.handle_sigterm)
        signal.signal(signal.SIGINT, self.handle_sigint)

        # Set to true when a shutdown was sheduled
        # Set to false when a sheduled shutdown shall be aborted
        self.shutdown_sheduled = False

        # init ipc if not given
        if not ipc:
            ipc = SharedMemoryIPC()

        self.rec = Recorder(ipc, self, ilog)

        self.converter = JsonConverter()

        # Define the ListWalker for the list of FrameElements
        self.listWalker = urwid.SimpleListWalker([])
        self.keyframelist = urwid.ListBox(self.listWalker)
        # Header of the UI-Frame (stays on top)
        self.headline = "Record Script - Exit:<q> Leave ConsoleWidget:<ESC> Use ConsoleWidget:<:>"
        self.header = urwid.Text(("caption3", self.headline))
        # Footer of the UI-Frame (stays on bottom, contains the console)
        loglevel = config["console_log_level"]
        self.console = ConsoleWidget(ipc, self.rec, self, loglevel)

        # HelpView
        self.helpView = HelpView()

        # Motor View
        self.motorView = MotorViewWidget()

        # Motor Info View
        self.motorInfoProvider = MotorInfoProvider()
        self.motorInfoLW = urwid.SimpleListWalker([])
        self.motorInfos = urwid.ListBox(self.motorInfoLW)
        self.motorInfoList = ScrollIndicatorWidget(self.motorInfos)

        # Frame View
        self.frameList = ScrollIndicatorWidget(self.keyframelist)

        # Initialise the Mainframe
        super(Mainframe, self).__init__(self.frameList, self.header, self.console)
        self.update_meta()

        # Select the Screen Type ('curses' or the default 'raw')
        if "screen" in config and config["screen"] == "curses":
            screen = urwid.curses_display.Screen()
        else:
            screen = urwid.raw_display.Screen()
            screen.set_terminal_properties(colors=256, bright_is_bold=False, has_underline=True)

        # Start the UI-Loop
        self.loop = urwid.MainLoop(self, palette, unhandled_input=self.unhandled_input, screen=screen)
        self.set_focus("footer")
        with ipc.record:
            if not ui_debug:
                self.loop.run()
class Mainframe(urwid.Frame):
    """ The top-level container for the GUI. Essentially the GUI itself.
    :param size: Irrellevant for us
    :param key: pressed key (bytes or unicode string)
    """

    def __init__(self, ui_debug=False, ipc=None):
        # init logging

        # Palette maps colors to attribute specifiers
        # All UI-Elements may be assigned these attributes
        palette = self.load_palette()
        # Set Encoding to UTF-8
        # usually urwid respects the system locale
        # but it is much more likely that the locale is wrong,
        # than that we ever need other encodings than utf-8.
        urwid.set_encoding("UTF-8")
        # register signals
        urwid.register_signal(DataFieldWidget, ["field_changed"])
        urwid.register_signal(KeyframeWidget, ["frame_changed"])
        signal.signal(signal.SIGTERM, self.handle_sigterm)
        signal.signal(signal.SIGINT, self.handle_sigint)

        # Set to true when a shutdown was sheduled
        # Set to false when a sheduled shutdown shall be aborted
        self.shutdown_sheduled = False

        # init ipc if not given
        if not ipc:
            ipc = SharedMemoryIPC()

        self.rec = Recorder(ipc, self, ilog)

        self.converter = JsonConverter()

        # Define the ListWalker for the list of FrameElements
        self.listWalker = urwid.SimpleListWalker([])
        self.keyframelist = urwid.ListBox(self.listWalker)
        # Header of the UI-Frame (stays on top)
        self.headline = "Record Script - Exit:<q> Leave ConsoleWidget:<ESC> Use ConsoleWidget:<:>"
        self.header = urwid.Text(("caption3", self.headline))
        # Footer of the UI-Frame (stays on bottom, contains the console)
        loglevel = config["console_log_level"]
        self.console = ConsoleWidget(ipc, self.rec, self, loglevel)

        # HelpView
        self.helpView = HelpView()

        # Motor View
        self.motorView = MotorViewWidget()

        # Motor Info View
        self.motorInfoProvider = MotorInfoProvider()
        self.motorInfoLW = urwid.SimpleListWalker([])
        self.motorInfos = urwid.ListBox(self.motorInfoLW)
        self.motorInfoList = ScrollIndicatorWidget(self.motorInfos)

        # Frame View
        self.frameList = ScrollIndicatorWidget(self.keyframelist)

        # Initialise the Mainframe
        super(Mainframe, self).__init__(self.frameList, self.header, self.console)
        self.update_meta()

        # Select the Screen Type ('curses' or the default 'raw')
        if "screen" in config and config["screen"] == "curses":
            screen = urwid.curses_display.Screen()
        else:
            screen = urwid.raw_display.Screen()
            screen.set_terminal_properties(colors=256, bright_is_bold=False, has_underline=True)

        # Start the UI-Loop
        self.loop = urwid.MainLoop(self, palette, unhandled_input=self.unhandled_input, screen=screen)
        self.set_focus("footer")
        with ipc.record:
            if not ui_debug:
                self.loop.run()

    def unhandled_input(self, key):
        """ Input accepted by no UI-Element ends up here.
        """
        if key == "q":
            raise urwid.ExitMainLoop()
        elif key == "m":
            if self.contents["body"] == (self.frameList, None):
                self.display_motor_ids()
            else:
                self.display_frames()
        elif key == "M":
            if isinstance(self.contents["body"][0], MetaViewWidget):
                self.display_frames()
            else:
                self.display_meta()
        elif key == "g":
            self.frameList.go_top()
        elif key == "G":
            self.frameList.go_bottom()
        elif key == ":":
            self.focus_position = "footer"
        elif key == "esc":
            self.focus_position = "body"
        elif key == "f12":
            self.reload_ipc()

    def reload_ipc(self):
        """
        Tries to reload the IPC
        """
        ipc = SharedMemoryIPC()
        self.rec.set_ipc(ipc)
        self.console.set_ipc(ipc)

    def __setattr__(self, name, value):
        """ Listen to some attribute-changes
        We hack in to urwid to check when the Focus changes
        """
        # Increase Consol-Size on focus
        if name is "focus_part":
            ilog.debug("Changing Main-Focus")
            body = self.contents["body"][0]
            if value is "footer":
                if isinstance(body, MetaViewWidget):
                    ilog.debug("Leaving Meta-View, better save it.")
                    body.save()
                self.console.expand()
                self.contents["body"] = (self.frameList, None)
            else:
                self.console.minimize()
        super(Mainframe, self).__setattr__(name, value)

    def append_keyframe(self, frame):
        """ Add a new keyframe to the UI.
        Called by the recorder to update the UI after a "record" command
        """

        # The converter gives back a nicer representation of the keyframe for
        # our purpose.
        values = self.converter.get_keyframe_data(frame)

        # A bit of error handling
        if not values:
            ilog.warning("Keyframe not loaded, because of previous error")
            return False

        # Determine new "current" keyframe-number
        current = len(self.listWalker) + 1

        # Make us a shiny new UI-element for this keyframe
        fe = KeyframeWidget(current, values)
        # Listen to Events by this UI-element
        urwid.connect_signal(fe, "frame_changed", self.on_frame_change)
        # Attach it to our ListViewWidget (by handing it to the walker)
        self.listWalker.append(fe)
        # Make sure the user can look at his new keyframe without additional
        # keypresses
        self.frameList.go_bottom()

        return True

    def pop_keyframe(self, framenumber=-1):
        """ Remove a Keyframe from the Keyframelist

        :param framenumber: the number of the frame to pop (0 == first element)
        """
        return self.listWalker.pop(framenumber)

    def update_meta(self):
        """ Update the Meta information in the header
        """
        meta = "name: %s | version: %s | last edited: %s" % (self.rec.name, self.rec.version, self.rec.last_edited)
        self.header = urwid.Text([("caption3", self.headline + "\n"), ("caption2", meta)])

    def display_keyframes(self, anim):
        """ display a new animation replacing the old one.

        :param anim: new animation in original dict representation (like in the file)
        """
        del self.listWalker[:]
        for frame in anim:
            if not self.append_keyframe(frame):
                # If an error occured while loading the keyframe for the UI
                # The Recorder itself SHOULD notice our negative feedback
                # however if it won't, this might induce problems.
                ilog.error("The new animation made me sick... check for unexpected behaviour")
                del self.listWalker[:]
                return False
        self.update_meta()
        self.display_frames()

    def write_frame(self, frame, field):
        """ write frame back to the recorder, if it was changed in the gui.
        """
        index = frame.framenumber - 1
        frame = self.listWalker[index]
        keyframedata = frame.get_data()
        anim = self.converter.get_dict(keyframedata)
        self.rec.save_step(
            "Changed Keyframe %03d, Field %s to value %s" % (frame.framenumber, field.title_text, field.edit_text)
        )
        self.rec.anim[index] = anim

    def is_valid(self):
        if len(self.listWalker) is 0:
            return False
        for keyframe in self.listWalker:
            if not keyframe.valid:
                return False
            if __debug__:
                ilog.debug("Keyframe %i is valid" % keyframe.framenumber)
        return True

    def on_frame_change(self, frame, field):
        if frame.valid:
            self.write_frame(frame, field)
            if __debug__:
                ilog.debug("Frame %03d updated because field %s was changed" % (frame.framenumber, field.title_text))
        ilog.debug("Redrawing Screen after Frame-change")

        # Having update-issues when the frame-title is changed
        # Calling draw_screen right away (as documented) will not help
        # I spent two days trying to figure out the reason for
        # this behaviour, found nothing and ended up using this:
        def call_draw(loop, user_data):
            loop.draw_screen()

        self.loop.set_alarm_in(0.01, call_draw)

    def display_motor_ids(self, group=None):
        # self.contents['body'] = (urwid.Filler(urwid.Text(
        #    motorIdsFormated)), None)
        success = True
        if group:
            success = self.motorView.highlight(group)
        self.contents["body"] = (self.motorView, None)
        self.focus_position = "body"
        return success

    def display_help(self, topic):
        """ Shows help to topic
        :param list topic: help arguments
        """
        if self.helpView.show_topic(topic):
            self.contents["body"] = (self.helpView, None)
            return True
        return False

    def display_meta(self):
        self.contents["body"] = (MetaViewWidget(self, self.rec), None)
        self.focus_position = "body"

    def display_frames(self):
        self.contents["body"] = (self.frameList, None)

    def display_motor_info(self, arg=None):
        infos = self.motorInfoProvider.get_motor_info(arg)
        if infos:
            del self.motorInfoLW[:]
            for widget in infos:
                self.motorInfoLW.append(widget)
            self.contents["body"] = (self.motorInfoList, None)
            return True
        return False

    def load_palette(self):
        """ Identifys the Theme requested by the user and tries to load it
        """

        def obtain_palette(theme):
            """ Makes the I/O to load a theme
            """
            try:
                path = find_resource("record_themes/" + theme)
                ilog.info("record color specification located as: %s" % path)
                with open(path, "r") as f:
                    palette = yaml.load(f)
                    ilog.debug("colors successfully loaded")
                    return palette
            except IOError:
                ilog.warn("color-file could not be opened!")
                self.helpmap = None
            except yaml.YAMLError as e:
                ilog.warn("color-file could not be parsed!")
                ilog.warn("Error in color-file: %s" % e)
            return []

        palette = []

        if "theme" in config:
            theme = config["theme"]
            ilog.debug("Using Theme %s" % theme)
            if not theme.endswith(".yaml"):
                theme += ".yaml"
        else:
            theme = "default.yaml"
            ilog.debug("No Theme specified in the config - using default")
        palette = obtain_palette(theme)
        if not palette and not theme == "default.yaml":
            ilog.warning("Could not load theme %s, trying default-theme instead!" % theme)
            palette = obtain_palette("default.yaml")

        return palette

    def handle_sigterm(self, signal, frame):
        """ Reacts on System-Termination
        by saving.
        """
        ilog.warning("Received Termination-Signal by system!")
        ilog.info("Trying to rescue Animation...")
        self.rec.dump("terminated", force=True)
        ilog.warning("Exiting... press ANY KEY to abort!")
        self.shutdown_sheduled = True

        # we are outside of the urwid-loop, so we have to refresh manually:
        self.loop.draw_screen()

        # shedule shutdown
        self.loop.set_alarm_in(5, self.exit_when_no_reaction)

    def handle_sigint(self, signal, frame):
        ilog.warning("Received SIGINT, but I have no way to handle this right now.")

    def exit_when_no_reaction(self, mainloop, user_data):
        if self.shutdown_sheduled:
            print "Exiting as a result of a SIGTERM, Good Bye"
            raise urwid.ExitMainLoop()
        else:
            ilog.debug("Sheduled Shutdown should be executed now, but it was abortet")

    def keypress(self, size, key):
        """ Handle Keypresses, before
        we let our children get them.
        """

        # abort shutdown
        if self.shutdown_sheduled:
            self.shutdown_sheduled = False
            ilog.info("Shutdown aborted.")
            return
        return super(Mainframe, self).keypress(size, key)
class Commander():
    """ Object that controls execution, help and
    autocompletion for all record-script commands.
    """
    def __init__(self, c_handler=None, recorder=None, jm=None, ui=None):
        self.console_handler = c_handler
        self.record = recorder
        self.jm = jm  # JointManager from the module 'record'
        self.ui = ui
        self.helpmap = None  # Holds the help (if loading succeds)
        self.all_commands = {}  # Convinence dict holding merged commands and aliases
        self.aliases = {}  # Holds alias definitions (if loading succeds)
        self.motor_info_provider = MotorInfoProvider()
        self.commands = {
            'help': self.cmd_help,
            'quit': self.cmd_quit,
            'exit': self.cmd_quit,
            'record': self.cmd_rec_record,
            'dump': self.cmd_rec_dump,
            'load': self.cmd_rec_load,
            'play': self.cmd_rec_play,
            'clear': self.cmd_rec_clear,
            'revert': self.cmd_rec_revert,
            'init': self.cmd_rec_init,
            'append': self.cmd_rec_append,
            'on': self.cmd_jm_on,
            'off': self.cmd_jm_off,
            'loglevel': self.cmd_loglevel,
            'copy': self.cmd_rec_copy,
            'move': self.cmd_rec_move,
            'pose': self.cmd_rec_pose,
            'desc': self.cmd_rec_desc,
            'meta': self.cmd_meta,
            'author': self.cmd_rec_author,
            'motors': self.cmd_motors,
            'motorinfo': self.cmd_motorinfo,
            'mirror': self.cmd_rec_mirror,
            'id': self.cmd_id,
            'undo': self.cmd_rec_undo,
            'redo': self.cmd_rec_redo,
            'xxxtestcommand': self.cmd_xxxtestcommand
        }

        self.autocompletions = {
            'load': self.ac_anim,
            'play': self.ac_anim,
            'append': self.ac_anim
        }

        self.load_aliases()
        self.load_help()

    def set_jm_ipc(self,ipc):
        self.jm.set_ipc(ipc)

    def cmd_loglevel(self, arguments):
        """ command function to set/get the loglevel
        """
        if len(arguments) > 1:
            logger.warn(
                "expected one or zero arguments, got %i" % (len(arguments)))
            return False
        if not arguments:
            logger.info(
                "Current loglevel is: %s" % self.console_handler.level)
            return True

        level = arguments[0]

        try:
            level = int(level)
        except ValueError:
            logger.warn("Loglevel must be an integer!")
            return False
        if 0 <= level <= 20:
            self.console_handler.setLevel(level)
            logger.info("Set Console Loglevel to %s" % level)
        elif 0 <= level <= 50:
            logger.warn("Console will not work properly at a loglevel this high! But I am doing as you please anyway...")
            self.console_handler.setLevel(level)
            logger.info("Set Console Loglevel to %s" % level)
        else:
            logger.warn(
                " %s is not a valid loglevel, ignoring command." % level)
            return False
        return True

    def cmd_quit(self, arguments):
        """ command function to quit the debugui
        """
        if arguments:
            logger.warn("What? Quit has no arguments.")
            return False
        logger.info("Quitting now...")
        raise ExitMainLoop

    def cmd_help(self, arguments):
        if not arguments:
            arguments = ['help']
        return self.ui.display_help(arguments)

    def cmd_rec_record(self, arguments):
        if not arguments:
            return self.record.record()
        if len(arguments) > 1:
            logger.warn(
                "record takes one argument at max! (got %s)" % len(arguments))
            return False
        else:
            try:
                arg = int(arguments[0])
                arg -= 1  # User-Presented list starts with position 1
                self.record.record(pos=arg)
            except ValueError:
                logger.warn("record argument must be a keyframe-number, not %s" % arguments[0])
                return False
        return True

    def cmd_rec_dump(self, arguments):
        if not arguments:
            logger.warn("No name specified. Use: dump <name>")
            return False
        if len(arguments) > 1:
            logger.warn("too many arguments for dump!")
            return False
        logger.info("speichern erfolgreich")
        return self.record.dump(arguments[0])

    def cmd_rec_load(self, arguments):
        if not arguments:
            logger.warn("Load what?")
            return False
        if len(arguments) > 1:
            logger.warn("Too many arguments for load. Use: load <name>")
            return False
        return self.record.load(arguments[0])

    def cmd_rec_play(self, arguments):
        if not arguments:
            return self.record.play()
        if len(arguments) is 1:
            arg = arguments[0]
            if is_animation_name(arg):
                return self.record.play(arg)
            elif is_selector(arg):
                return self.record.play(selector=arg)
            else:
                logger.warn("Your argument is neighter a animation-name nor a valid frame-selector")
                return False
        elif len(arguments) is 2:
            selector = arguments[0]
            name = arguments[1]
            if not is_animation_name(name):
                logger.warn("The Animation you asked for does not appear to exist")
                return False
            if not is_selector(selector):
                logger.warn("The selector you specified is invalid")
                return False
            return self.record.play(name, selector=selector)
        elif len(arguments) > 2:
            logger.warn("Too many arguments for play. Use: play [selector] [name]")
            return False

    def cmd_rec_clear(self, arguments):
        if arguments:
            logger.warn("What shall I do with the argument(s) ?!?")
            return False
        return self.record.clear()

    def cmd_rec_revert(self, arguments):
        if not arguments:
            return self.record.revert()
        elif len(arguments) is not 1:
            logger.warn(
                "Too many arguments for revert. Use: revert [framenumber]")
            return False
        return self.record.revert(arguments[0])

    def cmd_rec_init(self, arguments):
        if arguments:
            logger.warn("What shall I do with the argument(s) ?!?")
            return False
        return self.record.init()

    def cmd_rec_append(self, arguments):
        if not arguments:
            logger.warn("Please tell me _what_ to append!")
            return False
        if len(arguments) > 1:
            logger.info("Trying to append %s animations..." % len(arguments))
        failures = []
        for arg in arguments:
            if not self.record.append(arg):
                failures.append(arg)
        if failures:
            logger.error(
                "Could not append following animations: %s" % failures)
            return False
        logger.info("All animations appended successfully!")
        return True

    def cmd_rec_copy(self, arguments):
        if not arguments:
            logger.warn("Please tell me _what_ to copy!")
            return False
        elif len(arguments) > 2:
            logger.warn(
                "I cannot copy with so many arguments (%s)" % len(arguments))
            return False
        try:
            arg1 = int(arguments[0])
            if not arg1 > 0:
                raise ValueError
            if len(arguments) is 2:
                arg2 = int(arguments[1])
                if not arg2 > 0:
                    raise ValueError
            else:
                arg2 = None
        except ValueError:
            logger.warn("All arguments to copy must be Keyframe-Id's!")
            return False
        return self.record.copy(arg1, arg2)

    def cmd_rec_move(self, arguments):
        if not arguments:
            logger.warn("Please tell me _what_ to move!")
            return False
        elif len(arguments) is not 2:
            logger.warn("move needs exactly 2 arguments")
            return False
        try:
            arg1 = int(arguments[0])
            arg2 = int(arguments[1])
            if not arg1 > 0 or not arg2 > 0:
                raise ValueError
        except ValueError:
            logger.warn("All arguments to move must be Keyframe-Id's!")
            return False
        return self.record.move(arg1, arg2)

    def cmd_rec_pose(self, arguments):
        if not arguments:
            logger.warn("Please tell me _what_ pose I should take!")
            return False
        elif len(arguments) is not 1:
            logger.warn("pose takes exactly _one_ keyframe-id as argument!")
            return False
        try:
            arg = int(arguments[0])
        except ValueError:
            logger.warn("invalid keyframe-id!")
            return False
        if not arg > 0:
            logger.warn("invalid keyframe-id")
            return False
        return self.record.pose(arg)

    def cmd_rec_mirror(self, arguments):
        if not arguments or not len(arguments) == 2:
            logger.warn("Usage: mirror <selector> <tag>")
            return False
        selector = arguments[0]
        tag = arguments[1]
        return self.record.mirror(selector, tag)

    def cmd_jm_on(self, arguments):
        if not arguments:
            return self.jm.on()
        if len(arguments) > 1:
            logger.info("Trying to switch on %s groups" % len(arguments))
            failures = []
            for arg in arguments:
                if not self.jm.on(arg):
                    failures.append(arg)
            if failures:
                logger.warn("Following Groups failed: %s" % failures)
                return False
            else:
                return True
        return self.jm.on(arguments[0])

    def cmd_jm_off(self, arguments):
        if not arguments:
            return self.jm.off()
        if len(arguments) > 1:
            logger.info("Trying to switch off %s groups" % len(arguments))
            failures = []
            for arg in arguments:
                if not self.jm.off(arg):
                    failures.append(arg)
            if failures:
                logger.warn("Following Groups failed: %s" % failures)
                return False
            else:
                return True
        return self.jm.off(arguments[0])

    def cmd_rec_desc(self, arguments):
        """ modifies description.
        Currently it displays for no arguments, otherwise it takes all
        arguments as the description-text
        using the command "meta" there will be a special edit/display window
        for the Animation Metadata
        """
        if not arguments:
            logger.info(self.record.description)
            return True
        else:
            desc = ""
            for item in arguments:
                desc += ' ' + item
            self.record.description = desc
            logger.info("Description changed (Animation not saved)")
            return True

    def cmd_rec_author(self, arguments):
        if not arguments:
            logger.info(self.record.author)
            return True
        else:
            author = ""
            for item in arguments:
                author += ' ' + item
            self.record.author = author
            logger.info("Author changed (Animation not saved)")
            return True

    def cmd_rec_undo(self, arguments):
        if not arguments:
            return self.record.undo()
        elif len(arguments) > 1:
            logger.info("Usage: undo [amount]")
            return False
        else:
            try:
                amount = int(arguments[0])
            except ValueError:
                logger.info("The amount must be a integer")
                return False
        return self.record.undo(amount)

    def cmd_rec_redo(self, arguments):
        if not arguments:
            return self.record.redo()
        elif len(arguments) > 1:
            logger.info("Usage: redo [amount]")
            return False
        else:
            try:
                amount = int(arguments[0])
            except ValueError:
                logger.info("The amount must be a integer")
                return False
        return self.record.redo(amount)

    def cmd_meta(self, arguments):
        if not arguments:
            self.ui.display_meta()
            return True
        else:
            logger.warn("What shall I do with the argument(s) ?!?")
            return False

    def cmd_motors(self, arguments):
        """ Shows a ASCII-Art overview of the darwin-motors.
        if there is a argument it will be interpreted as
        motor group and the motors belonging to that group
        will be highlighted
        """
        if not arguments:
            return self.ui.display_motor_ids()
        elif len(arguments) is 1:
            return self.ui.display_motor_ids(arguments[0].lower())
        else:
            logger.warn("Too many arguments (must be one or none)!")
            return False

    def cmd_motorinfo(self, arguments):
        """ Gives Information on motors or a subset of motors,
        when an argument is given
        """
        if not arguments:
            return self.ui.display_motor_info()
        elif len(arguments) is 1:
            return self.ui.display_motor_info(arguments[0].lower())
        else:
            logger.warn("Too many arguments (must be one or none)!")
            return False

    def cmd_id(self, arguments):
        """ Returns the Motor ID(s) belonging to a given tag
        """
        if not arguments:
            logger.info("Usage: id <motortag>")
            return False
        if len(arguments) > 1:
            logger.warning("Sorry currently you can ask for only ONE tag")
            return False
        return self.motor_info_provider.report_id(arguments[0].lower())

    def cmd_xxxtestcommand(self, arguments):
        """ Testcommand to test for the Commander Connectivity.
        Changing this will cause a test to fail :)
        """
        logger.info("pong (Der Commander hört dir zu)")
        return 42

    def get_commands(self):
        return self.commands

    def autocomplete(self, cmd, arguments):

        # no arguments => extend command itself
        if not arguments:
            if not cmd:
                logger.debug("Nothing to autocomplete")
                return False
            possible = []  # possible completions
            for key in self.all_commands:
                if key.startswith(cmd):
                    possible.append(key)

        # We have some arguments => extend them if possible
        else:
            if cmd in self.autocompletions:
                possible = self.autocompletions[cmd](arguments)
            else:
                logger.warn("Sorry, autocomplete not implemented here (yet)")
                return False

        # Sort and return our findings
        # The UI will have to do the rest
        possible = sorted(set(possible))
        return possible

    def has_command(self, cmd):
        return cmd in self.commands or cmd in self.aliases

    def run(self, command, arguments):
        """ Execute given command with given parameters

        :param str command: Command to be executed
        :param list arguments: List of arguments
        """
        if not command in self.commands:
            if command in self.aliases:
                command = self.aliases[command]
            else:
                logger.warn('whoopsie! Command %s does not appear to exist!')
                return False
        new_args = []
        for argument in arguments:
            if type(argument) == str:
                new_args.append(argument.lower())
            else:
                new_args.append(argument)
        success = self.commands[command](new_args)
        if not success:
            logger.debug("record-command returned as a failure")
        return success

    def load_help(self):
        """ Parse the yaml-file with the help information
        """
        try:
            path = bitbots.util.find_resource('record_help.yaml')
            with open(path, 'r') as f:
                self.helpmap = yaml.load(f)
                logger.debug('help-file loaded')
        except IOError:
            # missing help is a serious fault, but does not force program termination
            logger.warn('help-file could not be opened! - no help availiable')
            self.helpmap = None
        except yaml.YAMLError as e:
            logger.warn('help-file could not be parsed! - no help availiable')
            logger.warn("Error in help-file: %s" % e)

    def load_aliases(self):
        """ Parse the yaml-file with the command alias information
        """
        try:
            path = bitbots.util.find_resource('record_aliases.yaml')
            with open(path, 'r') as f:
                self.aliases = yaml.load(f)
                logger.debug('alias-file loaded')
        except IOError:
            # Missing Aliases are not considered to be critical, though we
            # should log it.
            logger.debug('Alias-file could not be opened! - no aliases availiable')
            return False

        # Next verify aliases. If the aliased command is unkown, we shall
        # remove it from the dict
        for alias, command in self.aliases.copy().iteritems():
            if alias in self.commands:
                logger.warn("The alias '%s' would override the existing command. I am sorry Dave, I'm afraid I can't do that!'" % alias)
                del self.aliases[alias]
                continue
            if not command in self.commands:
                logger.warn("The command '%s' for the alias '%s' could not be found!" % (command, alias))
                del self.aliases[alias]

        # For convinece we build a merged dict of aliases and 'real' commands
        self.all_commands = self.aliases.copy()
        self.all_commands.update(self.commands)
        return True

    def ac_anim(self, arguments):
        if not arguments:
            logger.warn("animation autocomplete received no string to complete")
            return []
        animstart = arguments[-1]
        animations = find_all_animation_names()
        if not animations:
            logger.debug("It seems the Resource Manager found no animation at all o.O")
        possible = []

        for anim in animations:
            if anim.startswith(animstart):
                possible.append(anim)
        return possible