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
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
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
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
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