o k`-@sddlZddlZddlmZmZddlTddlmZddlm Z ddl m Z m Z ddl mZmZmZmZddlmZdd lmZdd lmZdd lmZdd lmZmZmZmZmZm Z m!Z!m"Z"dd l#m$Z$ddl%m&Z&Gddde'Z(dS)N) IntOption ListOption)*)IPermissionRequestor) ISearchSource)format_datetime user_time)Markupescape find_elementtag) Paginator)quote_query_string)_)IRequestHandler)INavigationContributorITemplateProvider accesskeyadd_link add_noticeadd_stylesheet add_warning web_context)IWikiSyntaxProvider) extract_linkc@seZdZdZeeeeee e e Z dZ eddddZedddd Zd d Zd d ZddZddZddZddZddZddZddZddZddZd d!Zd"d#Zd$d%Zd&d'Z d(d)Z!d*d+Z"d,S)- SearchModulez$Controller for the search sub-system searchmin_query_lengthzIMinimum length of query string allowed when performing a search. default_disabled_filtersapSpecifies which search filters should be disabled by default on the search page. This will also restrict the filters for the quick search function. The filter names defined by default components are: `wiki`, `ticket`, `milestone` and `changeset`. For plugins, look for their implementation of the ISearchSource interface, in the `get_search_filters()` method, the first member of returned tuple. Once disabled, search filters can still be manually enabled by the user on the search page. )doccCsdSNrselfreqr#r#4/usr/lib/python3/dist-packages/trac/search/web_ui.pyget_active_navigation_itemBz'SearchModule.get_active_navigation_itemccs<d|jvrddtjtd|jt|ddfVdSdS)N SEARCH_VIEWmainnavrSearch)hrefr)permr arr.rrr$r#r#r'get_navigation_itemsEs  z!SearchModule.get_navigation_itemscCsdgS)Nr*r#r%r#r#r'get_permission_actionsMsz#SearchModule.get_permission_actionscCstd|jduS)Nz/search(?:/opensearch)?$)rematch path_infor$r#r#r' match_requestRs zSearchModule.match_requestc Cs|jd|jdkrdiddifS|jd}g}|jD] }|||p'gq|jddd | ||}| ||||}|r|j d d }| ||||d <| d r]|dd}|||}|rx||||} | rx||||| |r|rd||jd<t|dd|fS)Nr*z/search/opensearchzopensearch.xml content_typez%application/opensearchdescription+xmlqcSs |dS)N)lower)fr#r#r'as z.SearchModule.process_request..)key noquickjumpF quickjump!r:,search.filterszcommon/css/search.cssz search.html)r/requirer6argsgetsearch_sourcesextendget_search_filterssort_get_selected_filters _prepare_datagetbool_check_quickjump startswith _parse_query _do_searchupdate_prepare_resultsjoinsessionr) r%r&queryavailable_filterssourcefiltersdatar?termsresultsr#r#r'process_requestVs4         zSearchModule.process_requestcCgSNr#r2r#r#r'get_htdocs_dirsxr)zSearchModule.get_htdocs_dirscCstddgS)Nz trac.search templates) pkg_resourcesresource_filenamer2r#r#r'get_templates_dirs{szSearchModule.get_templates_dirscCr^r_r#r2r#r#r'get_wiki_syntaxr)zSearchModule.get_wiki_syntaxccsd|jfVdSr") _format_linkr2r#r#r'get_link_resolversszSearchModule.get_link_resolversc Csj||\}}}|r |jj|d}|r|dt|dd7}n |jt|}||7}tj|d|dS)N)r9&r:r)class_r.) split_linkr.rrr r0) r% formatternstargetlabelpathrVfragmentr.r#r#r'rfszSearchModule._format_linkcsjfdd|D}|s3jd}|r*tdd|Dfdd|dD}|Sfdd|D}|S)zUReturn selected filters or the default filters if none was selected. cs"g|] }|djvr|dqS)r)rE.0r<)r&r#r' s"z6SearchModule._get_selected_filters..rCcSsg|]}|ddqS)rr#rqr#r#r'rsscsg|]}|vr|qSr#r#rq)available_filters_dictr#r'rssrBcsBg|]}|djvrt|dkst|dkr|dr|dqS)rrrt)r lenrqr2r#r'rss  )rUrFdictsplit)r%r&rWrYsession_filtersr#)rur&r%r'rKs z"SearchModule._get_selected_filterscsfdd|D|dgdS)Ncs(g|]}|d|d|dvdqS)rr:)namernactiver#rqrYr#r'rss   z.SearchModule._prepare_data..)rYrVr@r\r#)r%r&rVrWrYr#r|r'rLs zSearchModule._prepare_datac Csd}|ddkr|j|}|}td|d}n#t|d}tt|j||d}|dur:|jd}|j }|jdd }|r}| |j pBdsFd }|rQ|t ||d S|jd d } |jd|fdg} t|ttdt| t|t| d||dSdS)zLook for search shortcutsNr/zBrowse repository path %(path)s)rorr.titleT)r.rz description TracSearchz#Quicksearchesr9)r?r:zYou arrived here through the quick-jump search feature. To instead search for the term %(term)s, click here.)help_urlterm search_url)r.browserrrr renvattribrFchildrenrO base_pathr emwikirrr r redirect) r%r&r?kwdquickjump_hrefrzrcontextlinkrrr#r#r'rNs6       zSearchModule._check_quickjumpcCs\g}td|D]#}|dur+|r+|d|dkr&|ddvr&|dd}||q|S)zBreak apart a search query into its various search terms. Terms are grouped implicitly by word boundary, or explicitly by (single or double) quotes. z(".*?")|('.*?')|(\s+)Nrz'"r:)r4rxstripappend)r%rVr[rr#r#r'_get_search_termss  zSearchModule._get_search_termscCsH||}|rt|dkst|d|jkr|St|td|jddS)zMParse query and refuse those which would result in a huge result set r:rzGSearch query too short. Query must be at least %(num)s characters long.numN)rrvrrr)r%r&rVr[r#r#r'rPs  zSearchModule._parse_querycCs:g}|jD]}|||||pgqt|ddddS)NcSs|dS)Nrtr#)xr#r#r'r=sz)SearchModule._do_search..T)r>reverse)rGrHget_search_resultssorted)r%r&r[rYr\rXr#r#r'rQs  zSearchModule._do_searchc s|jjdddd}z t||d|j}Wnty1t|td|dd}t||d|j}Ynwt|D]\}}|d|dt|t |d|d|d d ||<q6g}| d }|D]$} |j j d d |D|j d| dd} || dt| td| dgq\gdfdd |D|_ddt|jddd|_|jr|j j t|dgt||j d|ddd} t|d| td|jr|j j t|dgt||j d|ddd} t|d| td|j j t|dgt||j ddd} || dS)Npager:)minzPage %(page)s is out of range.)rrrtrr-)r.r~dateauthorexcerptcSsg|]}|dfqS)onr#rqr#r#r'rssz1SearchModule._prepare_results..r9)r9rr?z Page %(num)dr)r.classstringr~csg|] }tt|qSr#)rwzip)rrpfieldsr#r'rsscurrentrnextz Next Pageprevz Previous Page)r9r?)r\ page_href)rEgetintr RESULTS_PER_PAGE TracErrorrr enumeraterrget_shown_pagesr.rrFrstr shown_pagesr current_page has_next_pagerrvrhas_previous_page) r%r&rYr\ridxresultpagedatar shown_pager next_href prev_hrefr#rr'rSs\         zSearchModule._prepare_resultsN)#__name__ __module__ __qualname____doc__ implementsrrrrrExtensionPointrrGrrrrr r(r1r3r7r]r`rdrergrfrKrLrNrrPrQrSr#r#r#r'r%s>" # r))rbr4 trac.configrr trac.core trac.permrtrac.search.apirtrac.util.datefmtrrtrac.util.htmlr r r r trac.util.presentationr trac.util.textrtrac.util.translationr trac.web.apirtrac.web.chromerrrrrrrr trac.wiki.apirtrac.wiki.formatterr Componentrr#r#r#r's       (