diff --git a/src/applications/typeahead/controller/PhabricatorTypeaheadFunctionHelpController.php b/src/applications/typeahead/controller/PhabricatorTypeaheadFunctionHelpController.php index aa15290ab4..dd29069ee5 100644 --- a/src/applications/typeahead/controller/PhabricatorTypeaheadFunctionHelpController.php +++ b/src/applications/typeahead/controller/PhabricatorTypeaheadFunctionHelpController.php @@ -1,150 +1,154 @@ getViewer(); $class = $request->getURIData('class'); $sources = id(new PhutilSymbolLoader()) ->setAncestorClass('PhabricatorTypeaheadDatasource') ->loadObjects(); if (!isset($sources[$class])) { return new Aphront404Response(); } $source = $sources[$class]; $application_class = $source->getDatasourceApplicationClass(); if ($application_class) { $result = id(new PhabricatorApplicationQuery()) ->setViewer($this->getViewer()) ->withClasses(array($application_class)) ->execute(); if (!$result) { return new Aphront404Response(); } } $source->setViewer($viewer); $title = pht('Typeahead Function Help'); $functions = $source->getAllDatasourceFunctions(); ksort($functions); $content = array(); $content[] = '= '.pht('Overview'); $content[] = pht( 'Typeahead functions are an advanced feature which allow you to build '. 'more powerful queries. This document explains functions available '. 'for the selected control.'. "\n\n". + 'For general help with search, see the [[ %s | Search User Guide ]] in '. + 'the documentation.'. + "\n\n". 'Note that different controls support //different// functions '. '(depending on what the control is doing), so these specific functions '. 'may not work everywhere. You can always check the help for a control '. - 'to review which functions are available for that control.'); + 'to review which functions are available for that control.', + PhabricatorEnv::getDoclink('Search User Guide')); $table = array(); $table_header = array( pht('Function'), pht('Token Name'), pht('Summary'), ); $table[] = '| '.implode(' | ', $table_header).' |'; $table[] = '|---|---|---|'; foreach ($functions as $function => $spec) { $spec = $spec + array( 'summary' => null, 'arguments' => null, ); if (idx($spec, 'arguments')) { $signature = '**'.$function.'(**//'.$spec['arguments'].'//**)**'; } else { $signature = '**'.$function.'()**'; } $name = idx($spec, 'name', ''); $summary = idx($spec, 'summary', ''); $table[] = '| '.$signature.' | '.$name.' | '.$summary.' |'; } $table = implode("\n", $table); $content[] = '= '.pht('Function Quick Reference'); $content[] = pht( 'This table briefly describes available functions for this control. '. 'For details on a particular function, see the corresponding section '. 'below.'); $content[] = $table; $content[] = '= '.pht('Using Typeahead Functions'); $content[] = pht( 'In addition to typing user and project names to build queries, you can '. 'also type the names of special functions which give you more options '. 'and the ability to express more complex queries.'. "\n\n". 'Functions have an internal name (like `viewer()`) and a '. 'human-readable name, like `Current Viewer`. In general, you can type '. 'either one to select the function. You can also click the '. '{nav icon=search} button on any typeahead control to browse available '. 'functions and find this documentation.'. "\n\n". 'This documentation uses the internal names to make it clear where '. 'tokens begin and end. Specifically, you will find queries written '. 'out like this in the documentation: '. "\n\n". '> viewer(), alincoln'. "\n\n". 'When this query is actually shown in the control, it will look more '. 'like this:'. "\n\n". '> {nav Current Viewer} {nav alincoln (Abraham Lincoln)}'); $middot = "\xC2\xB7"; foreach ($functions as $function => $spec) { $arguments = idx($spec, 'arguments', ''); $name = idx($spec, 'name'); $content[] = '= '.$function.'('.$arguments.') '.$middot.' '.$name; $content[] = $spec['description']; } $content = implode("\n\n", $content); $content_box = PhabricatorMarkupEngine::renderOneObject( id(new PhabricatorMarkupOneOff())->setContent($content), 'default', $viewer); $header = id(new PHUIHeaderView()) ->setHeader($title); $document = id(new PHUIDocumentView()) ->setHeader($header) ->setFontKit(PHUIDocumentView::FONT_SOURCE_SANS) ->appendChild($content_box); $crumbs = $this->buildApplicationCrumbs(); $crumbs->addTextCrumb(pht('Function Help')); return $this->buildApplicationPage( array( $crumbs, $document, ), array( 'title' => $title, )); } } diff --git a/src/docs/user/userguide/jump.diviner b/src/docs/user/userguide/jump.diviner index 705aa3a457..24f1ca4438 100644 --- a/src/docs/user/userguide/jump.diviner +++ b/src/docs/user/userguide/jump.diviner @@ -1,27 +1,40 @@ -@title Jump Nav User Guide +@title Search User Guide: Shortcuts @group userguide -Command reference for the jump nav. +Command reference for global search shorcuts. -= Overview = +Overview +======== -The jump nav provides a quick way to navigate to tools and objects: just type -a navigational command into the box and press return. +Phabricator's global search bar automatically interprets certain commands as +shortcuts to make it easy to navigate to specific places. -= Supported Commands = +To use these shortcuts, just type them into the global search bar in the main +menu and press return. For example, enter `T123` to jump to the corresponding +task quickly. + +Supported Commands +======== - **T** - Jump to Maniphest. - **T123** - Jump to Maniphest Task 123. - **D** - Jump to Differential. - **D123** - Jump to Differential Revision 123. - **r** - Jump to Diffusion. - **rXYZ** - Jump to Diffusion Repository XYZ. - **rXYZabcdef** - Jump to Diffusion Commit rXYZabcdef. - **r ** - Search for repositories by name. - **u** - Jump to People - **u username** - Jump to username's Profile - **p** - Jump to Project - **p Some Project** - Jump to Project: Some Project - **s SymbolName** - Jump to Symbol SymbolName - **task: (new title)** - Jumps to Task Creation Page with pre-filled title. - **(default)** - Search for input. + +Next Steps +========== + +Continue by: + + - returning to the @{article:Search User Guide}. diff --git a/src/docs/user/userguide/search.diviner b/src/docs/user/userguide/search.diviner new file mode 100644 index 0000000000..f2d564bc75 --- /dev/null +++ b/src/docs/user/userguide/search.diviner @@ -0,0 +1,125 @@ +@title Search User Guide +@group userguide + +Introduction to searching for documents in Phabricator. + +Overview +======== + +Phabricator has two major ways to search for documents and objects (like tasks, +code reviews, users, wiki documents, and so on): **global search** and +**application search**. + +**Global search** allows you to search across multiple document types at once, +but has fewer options for refining a search. It's a good general-purpose +search, and helpful if you're searching for a text string. + +**Application search** allows you to search within an application (like +Maniphest) for documents of a specific type. Because application search is only +searching one type of object, it can provide more powerful options for +filtering, ordering, and displaying the results. + +Both types of search share many of the same features. This document walks +through how to use search and how to take advantage of some of the advanced +options. + + +Global Search +============= + +Global search allows you to search across multiple document types at once. +You can access global search by entering a search query in the main menu bar. + +By default, global search queries search all document types: for example, they +will find matching tasks, commits, wiki documents, users, etc. You can use the +dropdown to the left of the search box to select a different search scope. + +If you choose the **Current Application** scope, Phabricator will search for +open documents in the current application. For example, if you're in Maniphest +and run a search, you'll get matching tasks. If you're in Phriction and run a +search, you'll get matching wiki documents. + +Some pages (like the 404 page) don't belong to an application, or belong to an +application which doesn't have any searchable documents. In these cases, +Phabricator will search all documents. + +To quickly **jump to an object** like a task, enter the object's ID in the +global search box and search for it. For example, you can enter `T123` or +`D456` to quickly jump to the corresponding task or code review, or enter a Git +commit hash to jump to the corresponding commit. For a complete list of +supported commands, see @{article:Search User Guide: Shortcuts}. + +After running a search, you can scroll up to add filters and refine the result +set. You can also select **Advanced Search** from the dropdown menu to jump +here immediately, or press return in the search box without entering a query. + +This interface supports standard Phabricator search and filtering features, +like **saved queries** and **typeaheads**. See below for more details on using +these features. + + +Application Search +================== + +Application search gives you a more powerful way to search one type of document, +like tasks. Most applications provide application search interfaces for the +documents or objects they let you create: these pages have queries in the left +menu, show objects or documents in the main content area, and have controls +for refining the results. + +These interfaces support **saved queries** and **typeaheads**. + + +Saving and Sharing Queries +============= + +If you have a query which you run often, you can save it for easy access. +To do this, click "Save Custom Query..." on the result screen. Choose a name +for your query and it will be saved in the left nav so you can run it again +with one click. + +You can use "Edit Queries..." to reorder queries or remove saved queries you +don't use anymore. + +If you drag a query to the top of the list, it will execute by default when +you load the relevant search interface. You can use this to make your default +view show the results you most often want. + +You can share queries with other users by sending them the URL. This will run +the same query for them with all the parameters you've set (they may see +different results than you do, because they may not have the same permisions). + + +Typeaheads +========== + +Typeaheads are text inputs which suggest options as you type. Typeaheads make +it easy to select users, projects, document types, and other kinds of objects +without typing their full names. + +For example, if you want to find tasks that a specific user created, you can +use the "Authors:" filter in Maniphest. The filter uses a typeahead control +to let you enter authors who you want to search for. + +To use a typeahead, enter the first few letters of the thing you want to +select. It will appear in a dropdown under your cursor, and you can select it +by clicking it (or using the arrow keys to highlight it, then pressing return). + +If you aren't sure about the exact name of what you're looking for, click the +browse button ({nav icon=search}) to the right of the input. This will let you +browse through valid results for the control. You can filter the results from +within the browse dialog to narrow them down. + +Some typeaheads support advanced selection functions which can let you build +more powerful queries. If a control supports functions, the "Browse" dialog +will show that advanced functions are available and give you a link to details +on which functions you can use. + +For example, the `members()` function lets you automatically select all of the +members of a project. You could use this with the "Authors" filter to find +tasks created by anyone on a certain team. + +Another useful function is the `viewer()` function, which works as though you'd +typed your own username when you run the query. However, if you send the query +to someone else, it will show results for //their// username when they run it. +This can be particularly useful when creating dashboard panels. diff --git a/src/view/page/menu/PhabricatorMainMenuSearchView.php b/src/view/page/menu/PhabricatorMainMenuSearchView.php index 196a22a07c..fe2b435458 100644 --- a/src/view/page/menu/PhabricatorMainMenuSearchView.php +++ b/src/view/page/menu/PhabricatorMainMenuSearchView.php @@ -1,223 +1,221 @@ application = $application; return $this; } public function getApplication() { return $this->application; } public function getID() { if (!$this->id) { $this->id = celerity_generate_unique_node_id(); } return $this->id; } public function render() { $user = $this->user; $target_id = celerity_generate_unique_node_id(); $search_id = $this->getID(); $button_id = celerity_generate_unique_node_id(); $input = phutil_tag( 'input', array( 'type' => 'text', 'name' => 'query', 'id' => $search_id, 'autocomplete' => 'off', )); $target = javelin_tag( 'div', array( 'id' => $target_id, 'class' => 'phabricator-main-menu-search-target', ), ''); $search_datasource = new PhabricatorSearchDatasource(); $scope_key = PhabricatorUserPreferences::PREFERENCE_SEARCH_SCOPE; Javelin::initBehavior( 'phabricator-search-typeahead', array( 'id' => $target_id, 'input' => $search_id, 'button' => $button_id, 'src' => $search_datasource->getDatasourceURI(), 'limit' => 10, 'placeholder' => pht('Search'), 'scopeUpdateURI' => '/settings/adjust/?key='.$scope_key, )); $primary_input = phutil_tag( 'input', array( 'type' => 'hidden', 'name' => 'search:primary', 'value' => 'true', )); $search_text = javelin_tag( 'span', array( 'aural' => true, ), pht('Search')); $selector = $this->buildModeSelector(); $form = phabricator_form( $user, array( 'action' => '/search/', 'method' => 'POST', ), phutil_tag_div('phabricator-main-menu-search-container', array( $input, phutil_tag( 'button', array( 'id' => $button_id, 'class' => 'phui-icon-view phui-font-fa fa-search', ), $search_text), $selector, $primary_input, $target, ))); return $form; } private function buildModeSelector() { $viewer = $this->getUser(); $items = array(); $items[] = array( 'name' => pht('Search'), ); $items[] = array( 'icon' => 'fa-globe', 'name' => pht('Search All Documents'), 'value' => 'all', ); $application_value = null; $application_icon = 'fa-dot-circle-o'; $application = $this->getApplication(); if ($application) { $application_value = get_class($application); if ($application->getApplicationSearchDocumentTypes()) { $application_icon = $application->getFontIcon(); } } $items[] = array( 'icon' => $application_icon, 'name' => pht('Search Current Application'), 'value' => PhabricatorSearchController::SCOPE_CURRENT_APPLICATION, ); $items[] = array( 'name' => pht('Saved Queries'), ); $engine = id(new PhabricatorSearchApplicationSearchEngine()) ->setViewer($viewer); $engine_queries = $engine->loadEnabledNamedQueries(); $query_map = mpull($engine_queries, 'getQueryName', 'getQueryKey'); foreach ($query_map as $query_key => $query_name) { if ($query_key == 'all') { // Skip the builtin "All" query since it's redundant with the default // setting. continue; } $items[] = array( 'icon' => 'fa-certificate', 'name' => $query_name, 'value' => $query_key, ); } $items[] = array( 'name' => pht('More Options'), ); $items[] = array( 'icon' => 'fa-search-plus', 'name' => pht('Advanced Search'), 'href' => '/search/query/advanced/', ); - /* TODO: Write this. $items[] = array( 'icon' => 'fa-book', 'name' => pht('User Guide: Search'), - 'href' => PhabricatorEnv::getDoclink('User Guide: Search'), + 'href' => PhabricatorEnv::getDoclink('Search User Guide'), ); - */ $scope_key = PhabricatorUserPreferences::PREFERENCE_SEARCH_SCOPE; $current_value = $viewer->loadPreferences()->getPreference( $scope_key, 'all'); $current_icon = 'fa-globe'; foreach ($items as $item) { if (idx($item, 'value') == $current_value) { $current_icon = $item['icon']; break; } } $selector = id(new PHUIButtonView()) ->addClass('phabricator-main-menu-search-dropdown') ->addSigil('global-search-dropdown') ->setMetadata( array( 'items' => $items, 'icon' => $current_icon, 'value' => $current_value, )) ->setIcon( id(new PHUIIconView()) ->addSigil('global-search-dropdown-icon') ->setIconFont($current_icon)) ->setDropdown(true); $input = javelin_tag( 'input', array( 'type' => 'hidden', 'sigil' => 'global-search-dropdown-input', 'name' => 'search:scope', 'value' => $current_value, )); $application_input = javelin_tag( 'input', array( 'type' => 'hidden', 'sigil' => 'global-search-dropdown-app', 'name' => 'search:application', 'value' => $application_value, )); return array($selector, $input, $application_input); } }