docs: def search(criteria, refresh=False, **kwargs):
      '''
      List known packages, available to the system.
  
      refresh
          force a refresh if set to True.
          If set to False (default) it depends on zypper if a refresh is
          executed.
  
      match (str)
          One of `exact`, `words`, `substrings`. Search for an `exact` match
          or for the whole `words` only. Default to `substrings` to patch
          partial words.
  
      provides (bool)
          Search for packages which provide the search strings.
  
      recommends (bool)
          Search for packages which recommend the search strings.
  
      requires (bool)
          Search for packages which require the search strings.
  
      suggests (bool)
          Search for packages which suggest the search strings.
  
      conflicts (bool)
          Search packages conflicting with search strings.
  
      obsoletes (bool)
          Search for packages which obsolete the search strings.
  
      file_list (bool)
          Search for a match in the file list of packages.
  
      search_descriptions (bool)
          Search also in package summaries and descriptions.
  
      case_sensitive (bool)
          Perform case-sensitive search.
  
      installed_only (bool)
          Show only installed packages.
  
      not_installed_only (bool)
          Show only packages which are not installed.
  
      details (bool)
          Show version and repository
  
      root
          operate on a different root directory.
  
      CLI Examples:
  
      .. code-block:: bash
  
          salt '*' pkg.search <criteria>
      '''
      ALLOWED_SEARCH_OPTIONS = {
              'provides': '--provides',
              'recommends': '--recommends',
              'requires': '--requires',
              'suggests': '--suggests',
              'conflicts': '--conflicts',
              'obsoletes': '--obsoletes',
              'file_list': '--file-list',
              'search_descriptions': '--search-descriptions',
              'case_sensitive': '--case-sensitive',
              'installed_only': '--installed-only',
              'not_installed_only': '-u',
              'details': '--details'
              }
  
      root = kwargs.get('root', None)
  
      if refresh:
          refresh_db(root)
  
      cmd = ['search']
      if kwargs.get('match') == 'exact':
          cmd.append('--match-exact')
      elif kwargs.get('match') == 'words':
          cmd.append('--match-words')
      elif kwargs.get('match') == 'substrings':
          cmd.append('--match-substrings')
  
      for opt in kwargs:
          if opt in ALLOWED_SEARCH_OPTIONS:
              cmd.append(ALLOWED_SEARCH_OPTIONS.get(opt))
  
      cmd.append(criteria)
      solvables = __zypper__(root=root).nolock.noraise.xml.call(*cmd).getElementsByTagName('solvable')
      if not solvables:
          raise CommandExecutionError(
              'No packages found matching \'{0}\''.format(criteria)
          )
  
      out = {}
      for solvable in solvables:
          out[solvable.getAttribute('name')] = dict()
          for k, v in solvable.attributes.items():
              out[solvable.getAttribute('name')][k] = v
  
      return out