def _manual_differences(previous_manual, new_manual):
  """
  Provides a description of how two manuals differ.
  """

  lines = []

  for attr in ('name', 'synopsis', 'description', 'commandline_options', 'signals', 'files', 'config_options'):
    previous_attr = getattr(previous_manual, attr)
    new_attr = getattr(new_manual, attr)

    if previous_attr != new_attr:
      lines.append("* Manual's %s attribute changed\n" % attr)

      if attr in ('name', 'synopsis', 'description'):
        lines.append('  Previously...\n\n%s\n' % previous_attr)
        lines.append('  Updating to...\n\n%s' % new_attr)
      elif attr == 'config_options':
        for config_name, config_attr in new_attr.items():
          previous = previous_attr.get(config_name)

          if previous is None:
            lines.append('  adding new config option => %s' % config_name)
          elif config_attr != previous:
            for attr in ('name', 'category', 'usage', 'summary', 'description'):
              if getattr(config_attr, attr) != getattr(previous, attr):
                lines.append('  modified %s (%s) => %s' % (config_name, attr, getattr(config_attr, attr)))

        for config_name in set(previous_attr.keys()).difference(new_attr.keys()):
          lines.append('  removing config option => %s' % config_name)
      else:
        added_items = set(new_attr.items()).difference(previous_attr.items())
        removed_items = set(previous_attr.items()).difference(new_attr.items())

        for added_item in added_items:
          lines.append('  adding %s => %s' % added_item)

        for removed_item in removed_items:
          lines.append('  removing %s => %s' % removed_item)

      lines.append('\n')

  return '\n'.join(lines)