Example #1
0
    def search(self, session, searchterms, keywords=None, order=None):
        # Stash the raw search terms, decide if this is cached or not
        raw_terms = searchterms[:]
        if keywords is None:
            srs = CachedSearchResultSet(self, raw_terms)
            if len(srs) > 0:
                return srs
        else:
            srs = SearchResultSet(self, raw_terms, [], [])

        # Choose how we are going to search
        if keywords is not None:
            def hits(term):
                return [int(h, 36) for h in keywords.get(term, [])]
        else:
            def hits(term):
                if term.endswith(':in'):
                    return self.TAGS.get(term.rsplit(':', 1)[0], [])
                else:
                    session.ui.mark(_('Searching for %s') % term)
                    return [int(h, 36) for h
                            in GlobalPostingList(session, term).hits()]

        # Replace some GMail-compatible terms with what we really use
        if 'tags' in self.config:
            for p in ('', '+', '-'):
                while p + 'is:unread' in searchterms:
                    where = searchterms.index(p + 'is:unread')
                    new = session.config.get_tags(type='unread')
                    if new:
                        searchterms[where] = p + 'in:%s' % new[0].slug
                for t in [term for term in searchterms
                          if term.startswith(p + 'tag:')]:
                    where = searchterms.index(t)
                    searchterms[where] = p + 'in:' + t.split(':', 1)[1]

        # If first term is a negative search, prepend an all:mail
        if searchterms and searchterms[0] and searchterms[0][0] == '-':
            searchterms[:0] = ['all:mail']

        r = []
        for term in searchterms:
            if term in STOPLIST:
                if session:
                    session.ui.warning(_('Ignoring common word: %s') % term)
                continue

            if term[0] in ('-', '+'):
                op = term[0]
                term = term[1:]
            else:
                op = None

            r.append((op, []))
            rt = r[-1][1]
            term = term.lower()

            if ':' in term:
                if term.startswith('body:'):
                    rt.extend(hits(term[5:]))
                elif term == 'all:mail':
                    rt.extend(range(0, len(self.INDEX)))
                elif term.startswith('in:'):
                    rt.extend(self.search_tag(term, hits))
                else:
                    t = term.split(':', 1)
                    fnc = plugins.get_search_term(t[0])
                    if fnc:
                        rt.extend(fnc(self.config, self, term, hits))
                    else:
                        rt.extend(hits('%s:%s' % (t[1], t[0])))
            else:
                rt.extend(hits(term))

        if r:
            results = set(r[0][1])
            for (op, rt) in r[1:]:
                if op == '+':
                    results |= set(rt)
                elif op == '-':
                    results -= set(rt)
                else:
                    results &= set(rt)
            # Sometimes the scan gets aborted...
            if keywords is None:
                results -= set([len(self.INDEX)])
        else:
            results = set()

        # Unless we are searching for invisible things, remove them from
        # results by default.
        exclude = []
        order = order or (session and session.order) or 'flat-index'
        if (results and (keywords is None) and
                ('tags' in self.config) and
                (not session or 'all' not in order)):
            invisible = self.config.get_tags(flag_hides=True)
            exclude_terms = ['in:%s' % i._key for i in invisible]
            for tag in invisible:
                tid = tag._key
                for p in ('in:%s', '+in:%s', '-in:%s'):
                    if ((p % tid) in searchterms or
                            (p % tag.name) in searchterms or
                            (p % tag.slug) in searchterms):
                        exclude_terms = []
            if len(exclude_terms) > 1:
                exclude_terms = ([exclude_terms[0]] +
                                 ['+%s' % e for e in exclude_terms[1:]])
            # Recursing to pull the excluded terms from cache as well
            exclude = self.search(session, exclude_terms).as_set()

        srs.set_results(results, exclude)
        if session:
            session.ui.mark(_('Found %d results (%d suppressed)'
                              ) % (len(results), len(srs.excluded())))
        return srs
Example #2
0
  def search(self, session, searchterms, keywords=None):
    if keywords:
      def hits(term):
        return [int(h, 36) for h in keywords.get(term, [])]
    else:
      def hits(term):
        session.ui.mark('Searching for %s' % term)
        return [int(h, 36) for h in GlobalPostingList(session, term).hits()]

    # Replace some GMail-compatible terms with what we really use
    for p in ('', '+', '-'):
      while p+'is:unread' in searchterms:
        searchterms[searchterms.index(p+'is:unread')] = p+'tag:New'
      while p+'in:spam' in searchterms:
        searchterms[searchterms.index(p+'in:spam')] = p+'tag:Spam'
      while p+'in:trash' in searchterms:
        searchterms[searchterms.index(p+'in:trash')] = p+'tag:Trash'

    # If first term is a negative search, prepend an all:mail
    if searchterms and searchterms[0] and searchterms[0][0] == '-':
      searchterms[:0] = ['all:mail']

    if len(self.CACHE.keys()) > 5000: self.CACHE = {}
    r = []
    for term in searchterms:
      if term in STOPLIST:
        if session:
          session.ui.warning('Ignoring common word: %s' % term)
        continue

      if term[0] in ('-', '+'):
        op = term[0]
        term = term[1:]
      else:
        op = None

      r.append((op, []))
      rt = r[-1][1]
      term = term.lower()

      if ':' in term:
        # FIXME: Make search words pluggable!
        if term.startswith('body:'):
          rt.extend(hits(term[5:]))
        elif term == 'all:mail':
          rt.extend(range(0, len(self.INDEX)))
        elif term.startswith('tag:'):
          rt.extend(self.search_tag(term, hits))
        else:
          t = term.split(':', 1)
          fnc = plugins.get_search_term(t[0])
          if fnc:
            rt.extend(fnc(self.config, term, hits))
          else:
            rt.extend(hits('%s:%s' % (t[1], t[0])))
      else:
        rt.extend(hits(term))

    if r:
      results = set(r[0][1])
      for (op, rt) in r[1:]:
        if op == '+':
          results |= set(rt)
        elif op == '-':
          results -= set(rt)
        else:
          results &= set(rt)
      # Sometimes the scan gets aborted...
      if not keywords:
        results -= set([len(self.INDEX)])
    else:
      results = set()

    if session:
      session.ui.mark('Found %d results' % len(results))
    return results
Example #3
0
    def search(self, session, searchterms, keywords=None):
        if keywords is not None:
            def hits(term):
                return [int(h, 36) for h in keywords.get(term, [])]
        else:
            def hits(term):
                session.ui.mark('Searching for %s' % term)
                return [int(h, 36) for h
                        in GlobalPostingList(session, term).hits()]

        # Stash the raw search terms
        raw_terms = searchterms[:]

        # Replace some GMail-compatible terms with what we really use
        if 'tags' in self.config:
            for p in ('', '+', '-'):
                while p + 'is:unread' in searchterms:
                    where = searchterms.index(p + 'is:unread')
                    searchterms[where] = p + 'tag:New'
                for t in [term for term in searchterms
                                        if term.startswith(p + 'tag:')]:
                    where = searchterms.index(t)
                    searchterms[where] = p + 'in:' + t.split(':', 1)[1]

        # If first term is a negative search, prepend an all:mail
        if searchterms and searchterms[0] and searchterms[0][0] == '-':
            searchterms[:0] = ['all:mail']

        r = []
        for term in searchterms:
            if term in STOPLIST:
                if session:
                    session.ui.warning('Ignoring common word: %s' % term)
                continue

            if term[0] in ('-', '+'):
                op = term[0]
                term = term[1:]
            else:
                op = None

            r.append((op, []))
            rt = r[-1][1]
            term = term.lower()

            if ':' in term:
                # FIXME: Make search words pluggable!
                if term.startswith('body:'):
                    rt.extend(hits(term[5:]))
                elif term == 'all:mail':
                    rt.extend(range(0, len(self.INDEX)))
                elif term.startswith('in:'):
                    rt.extend(self.search_tag(term, hits))
                else:
                    t = term.split(':', 1)
                    fnc = plugins.get_search_term(t[0])
                    if fnc:
                        rt.extend(fnc(self.config, self, term, hits))
                    else:
                        rt.extend(hits('%s:%s' % (t[1], t[0])))
            else:
                rt.extend(hits(term))

        if r:
            results = set(r[0][1])
            for (op, rt) in r[1:]:
                if op == '+':
                    results |= set(rt)
                elif op == '-':
                    results -= set(rt)
                else:
                    results &= set(rt)
            # Sometimes the scan gets aborted...
            if keywords is None:
                results -= set([len(self.INDEX)])
        else:
            results = set()

        # Unless we are searching for invisible things, remove them from
        # results by default.
        exclude = []
        if (results and (keywords is None) and
                ('tags' in self.config) and
                (not session or 'all' not in session.order)):
            invisible = self.config.sys.get('invisible_tags', [])
            exclude_terms = ['in:%s' % i for i in invisible]
            for tid in invisible:
                tag = self.config.tags[tid]
                for p in ('in:%s', '+in:%s', '-in:%s'):
                    if ((p % tid) in searchterms or
                            (p % tag.name) in searchterms or
                            (p % tag.slug) in searchterms):
                        exclude_terms = []
            for term in exclude_terms:
                exclude.extend(self.search_tag(term, hits))

        srs = SearchResultSet(self, raw_terms, results, exclude)
        if session:
            session.ui.mark(('Found %d results (%d suppressed)'
                             ) % (len(results), len(srs.excluded())))
        return srs
Example #4
0
    def search(self, session, searchterms, keywords=None):
        if keywords is not None:

            def hits(term):
                return [int(h, 36) for h in keywords.get(term, [])]
        else:

            def hits(term):
                session.ui.mark('Searching for %s' % term)
                return [
                    int(h, 36)
                    for h in GlobalPostingList(session, term).hits()
                ]

        # Stash the raw search terms
        raw_terms = searchterms[:]
        srs = CachedSearchResultSet(self, raw_terms)
        if len(srs) > 0:
            return srs

        # Replace some GMail-compatible terms with what we really use
        if 'tags' in self.config:
            for p in ('', '+', '-'):
                while p + 'is:unread' in searchterms:
                    where = searchterms.index(p + 'is:unread')
                    searchterms[where] = p + 'tag:New'
                for t in [
                        term for term in searchterms
                        if term.startswith(p + 'tag:')
                ]:
                    where = searchterms.index(t)
                    searchterms[where] = p + 'in:' + t.split(':', 1)[1]

        # If first term is a negative search, prepend an all:mail
        if searchterms and searchterms[0] and searchterms[0][0] == '-':
            searchterms[:0] = ['all:mail']

        r = []
        for term in searchterms:
            if term in STOPLIST:
                if session:
                    session.ui.warning('Ignoring common word: %s' % term)
                continue

            if term[0] in ('-', '+'):
                op = term[0]
                term = term[1:]
            else:
                op = None

            r.append((op, []))
            rt = r[-1][1]
            term = term.lower()

            if ':' in term:
                # FIXME: Make search words pluggable!
                if term.startswith('body:'):
                    rt.extend(hits(term[5:]))
                elif term == 'all:mail':
                    rt.extend(range(0, len(self.INDEX)))
                elif term.startswith('in:'):
                    rt.extend(self.search_tag(term, hits))
                else:
                    t = term.split(':', 1)
                    fnc = plugins.get_search_term(t[0])
                    if fnc:
                        rt.extend(fnc(self.config, self, term, hits))
                    else:
                        rt.extend(hits('%s:%s' % (t[1], t[0])))
            else:
                rt.extend(hits(term))

        if r:
            results = set(r[0][1])
            for (op, rt) in r[1:]:
                if op == '+':
                    results |= set(rt)
                elif op == '-':
                    results -= set(rt)
                else:
                    results &= set(rt)
            # Sometimes the scan gets aborted...
            if keywords is None:
                results -= set([len(self.INDEX)])
        else:
            results = set()

        # Unless we are searching for invisible things, remove them from
        # results by default.
        exclude = []
        if (results and (keywords is None) and ('tags' in self.config)
                and (not session or 'all' not in session.order)):
            invisible = self.config.get_tags(flag_hides=True)
            exclude_terms = ['in:%s' % i._key for i in invisible]
            for tag in invisible:
                tid = tag._key
                for p in ('in:%s', '+in:%s', '-in:%s'):
                    if ((p % tid) in searchterms
                            or (p % tag.name) in searchterms
                            or (p % tag.slug) in searchterms):
                        exclude_terms = []
            for term in exclude_terms:
                exclude.extend(self.search_tag(term, hits))

        srs.set_results(results, exclude)
        if session:
            session.ui.mark(('Found %d results (%d suppressed)') %
                            (len(results), len(srs.excluded())))
        return srs
Example #5
0
    def search(self, session, searchterms, keywords=None):
        if keywords:

            def hits(term):
                return [int(h, 36) for h in keywords.get(term, [])]
        else:

            def hits(term):
                session.ui.mark('Searching for %s' % term)
                return [
                    int(h, 36)
                    for h in GlobalPostingList(session, term).hits()
                ]

        # Replace some GMail-compatible terms with what we really use
        for p in ('', '+', '-'):
            while p + 'is:unread' in searchterms:
                searchterms[searchterms.index(p + 'is:unread')] = p + 'tag:New'
            while p + 'in:spam' in searchterms:
                searchterms[searchterms.index(p + 'in:spam')] = p + 'tag:Spam'
            while p + 'in:trash' in searchterms:
                searchterms[searchterms.index(p +
                                              'in:trash')] = p + 'tag:Trash'

        # If first term is a negative search, prepend an all:mail
        if searchterms and searchterms[0] and searchterms[0][0] == '-':
            searchterms[:0] = ['all:mail']

        if len(self.CACHE.keys()) > 5000: self.CACHE = {}
        r = []
        for term in searchterms:
            if term in STOPLIST:
                if session:
                    session.ui.warning('Ignoring common word: %s' % term)
                continue

            if term[0] in ('-', '+'):
                op = term[0]
                term = term[1:]
            else:
                op = None

            r.append((op, []))
            rt = r[-1][1]
            term = term.lower()

            if ':' in term:
                # FIXME: Make search words pluggable!
                if term.startswith('body:'):
                    rt.extend(hits(term[5:]))
                elif term == 'all:mail':
                    rt.extend(range(0, len(self.INDEX)))
                elif term.startswith('tag:'):
                    rt.extend(self.search_tag(term, hits))
                else:
                    t = term.split(':', 1)
                    fnc = plugins.get_search_term(t[0])
                    if fnc:
                        rt.extend(fnc(self.config, term, hits))
                    else:
                        rt.extend(hits('%s:%s' % (t[1], t[0])))
            else:
                rt.extend(hits(term))

        if r:
            results = set(r[0][1])
            for (op, rt) in r[1:]:
                if op == '+':
                    results |= set(rt)
                elif op == '-':
                    results -= set(rt)
                else:
                    results &= set(rt)
            # Sometimes the scan gets aborted...
            if not keywords:
                results -= set([len(self.INDEX)])
        else:
            results = set()

        if session:
            session.ui.mark('Found %d results' % len(results))
        return results