Print table of tools available in the suite.

        Args:
            context_name (str): If provided, only print the tools from this
                context.

def print_tools(self, buf=sys.stdout, verbose=False, context_name=None):
        """Print table of tools available in the suite.

        Args:
            context_name (str): If provided, only print the tools from this
                context.
        """
        def _get_row(entry):
            context_name_ = entry["context_name"]
            tool_alias = entry["tool_alias"]
            tool_name = entry["tool_name"]
            properties = []
            col = None

            variant = entry["variant"]
            if isinstance(variant, set):
                properties.append("(in conflict)")
                col = critical
                if verbose:
                    package = ", ".join(x.qualified_package_name for x in variant)
                else:
                    v = iter(variant).next()
                    package = "%s (+%d more)" % (v.qualified_package_name,
                                                 len(variant) - 1)
            else:
                package = variant.qualified_package_name

            if tool_name == tool_alias:
                tool_name = "-"
            else:
                properties.append("(aliased)")
                if col is None:
                    col = alias_col

            msg = " ".join(properties)
            row = [tool_alias, tool_name, package, context_name_, msg]
            return row, col

        if context_name:
            self._context(context_name)  # check context exists
            context_names = [context_name]
        else:
            context_names = sorted(self.contexts.iterkeys())

        rows = [["TOOL", "ALIASING", "PACKAGE", "CONTEXT", ""],
                ["----", "--------", "-------", "-------", ""]]
        colors = [None, None]

        entries_dict = defaultdict(list)
        for d in self.get_tools().itervalues():
            entries_dict[d["context_name"]].append(d)

        if verbose:
            # add hidden entries
            for d in self.hidden_tools:
                d_ = d.copy()
                d_["hidden"] = True
                entries_dict[d["context_name"]].append(d_)

            # add conflicting tools
            for docs in self.tool_conflicts.itervalues():
                for d in docs:
                    d_ = d.copy()
                    d_["conflicting"] = True
                    entries_dict[d["context_name"]].append(d_)

        for i, context_name in enumerate(context_names):
            entries = entries_dict.get(context_name, [])
            if entries:
                if i:
                    rows.append(('', '', '', '', ''))
                    colors.append(None)

                entries = sorted(entries, key=lambda x: x["tool_alias"].lower())
                for entry in entries:
                    row, col = _get_row(entry)
                    if "hidden" in entry:
                        row[-1] = "(hidden)"
                        rows.append(row)
                        colors.append(warning)
                    elif "conflicting" in entry:
                        row[-1] = "(not visible)"
                        rows.append(row)
                        colors.append(warning)
                    else:
                        rows.append(row)
                        colors.append(col)

        if rows:
            _pr = Printer(buf)
            for col, line in zip(colors, columnise(rows)):
                _pr(line, col)
        else:
            _pr("No tools available.")