From ccd1ebb25686045232d9c325a9c43a1338fc901c Mon Sep 17 00:00:00 2001 From: epriestley Date: Sat, 11 Apr 2020 10:18:31 -0700 Subject: [PATCH] Port "arc prompts" from wilds and fix a path issue in shell completion Summary: Ref T13490. Bring "arc prompts" from "wilds" and hook it into the prompt in "arc shell-complete". See D21069. Fix an issue where the shell hook tested for a path other than the path it writes to. Test Plan: Ran "arc shell-complete" with no hook and got a prompt. Shell completed things. Ran "arc prompts shell-complete". Maniphest Tasks: T13490 Differential Revision: https://secure.phabricator.com/D21085 --- src/__phutil_library_map__.php | 2 + .../workflow/ArcanistPromptsWorkflow.php | 80 +++++++++++++++++++ .../ArcanistShellCompleteWorkflow.php | 5 +- src/workflow/ArcanistWorkflow.php | 60 ++++++++++++++ support/shell/hooks/bash-completion.sh | 5 +- 5 files changed, 149 insertions(+), 3 deletions(-) create mode 100644 src/toolset/workflow/ArcanistPromptsWorkflow.php diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index c5db3727..d5625807 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -370,6 +370,7 @@ phutil_register_library_map(array( 'ArcanistPlusOperatorOnStringsXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistPlusOperatorOnStringsXHPASTLinterRuleTestCase.php', 'ArcanistProjectConfigurationSource' => 'config/source/ArcanistProjectConfigurationSource.php', 'ArcanistPrompt' => 'toolset/ArcanistPrompt.php', + 'ArcanistPromptsWorkflow' => 'toolset/workflow/ArcanistPromptsWorkflow.php', 'ArcanistPublicPropertyXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistPublicPropertyXHPASTLinterRule.php', 'ArcanistPublicPropertyXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistPublicPropertyXHPASTLinterRuleTestCase.php', 'ArcanistPuppetLintLinter' => 'lint/linter/ArcanistPuppetLintLinter.php', @@ -1330,6 +1331,7 @@ phutil_register_library_map(array( 'ArcanistPlusOperatorOnStringsXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistProjectConfigurationSource' => 'ArcanistWorkingCopyConfigurationSource', 'ArcanistPrompt' => 'Phobject', + 'ArcanistPromptsWorkflow' => 'ArcanistWorkflow', 'ArcanistPublicPropertyXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistPublicPropertyXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistPuppetLintLinter' => 'ArcanistExternalLinter', diff --git a/src/toolset/workflow/ArcanistPromptsWorkflow.php b/src/toolset/workflow/ArcanistPromptsWorkflow.php new file mode 100644 index 00000000..104bbf8a --- /dev/null +++ b/src/toolset/workflow/ArcanistPromptsWorkflow.php @@ -0,0 +1,80 @@ + +EOTEXT +); + + return $this->newWorkflowInformation() + ->addExample(pht('**prompts** __workflow__')) + ->setHelp($help); + } + + public function getWorkflowArguments() { + return array( + $this->newWorkflowArgument('argv') + ->setWildcard(true), + ); + } + + public function runWorkflow() { + $argv = $this->getArgument('argv'); + + if (!$argv) { + throw new PhutilArgumentUsageException( + pht('Provide a workflow to list prompts for.')); + } + + $runtime = $this->getRuntime(); + $workflows = $runtime->getWorkflows(); + + $workflow_key = array_shift($argv); + $workflow = idx($workflows, $workflow_key); + + if (!$workflow) { + throw new PhutilArgumentUsageException( + pht( + 'Workflow "%s" is unknown. Supported workflows are: %s.', + $workflow_key, + implode(', ', array_keys($workflows)))); + } + + $prompts = $workflow->getPromptMap(); + if (!$prompts) { + echo tsprintf( + "%s\n", + pht('This workflow does not have any prompts.')); + return 0; + } + + foreach ($prompts as $prompt) { + echo tsprintf( + "**%s**\n", + $prompt->getKey()); + echo tsprintf( + "%s\n", + $prompt->getDescription()); + } + + return 0; + } + +} diff --git a/src/toolset/workflow/ArcanistShellCompleteWorkflow.php b/src/toolset/workflow/ArcanistShellCompleteWorkflow.php index 9d65bc59..4fc1fb0a 100644 --- a/src/toolset/workflow/ArcanistShellCompleteWorkflow.php +++ b/src/toolset/workflow/ArcanistShellCompleteWorkflow.php @@ -226,7 +226,10 @@ EOTEXT $log->writeSuccess( pht('INSTALL'), - pht('Installing shell completion support for "%s".', $shell)); + pht( + 'Installing shell completion support for "%s" into "%s".', + $shell, + $file_display)); if ($replace) { $replace_pos = $matches[0][1]; diff --git a/src/workflow/ArcanistWorkflow.php b/src/workflow/ArcanistWorkflow.php index 76d18d94..8e59052a 100644 --- a/src/workflow/ArcanistWorkflow.php +++ b/src/workflow/ArcanistWorkflow.php @@ -77,6 +77,7 @@ abstract class ArcanistWorkflow extends Phobject { private $configurationSourceList; private $hardpointEngine; + private $promptMap; final public function setToolset(ArcanistToolset $toolset) { $this->toolset = $toolset; @@ -2333,4 +2334,63 @@ abstract class ArcanistWorkflow extends Phobject { return $engine; } + protected function newPrompts() { + return array(); + } + + protected function newPrompt($key) { + return id(new ArcanistPrompt()) + ->setWorkflow($this) + ->setKey($key); + } + + public function hasPrompt($key) { + $map = $this->getPromptMap(); + return isset($map[$key]); + } + + public function getPromptMap() { + if ($this->promptMap === null) { + $prompts = $this->newPrompts(); + assert_instances_of($prompts, 'ArcanistPrompt'); + + $map = array(); + foreach ($prompts as $prompt) { + $key = $prompt->getKey(); + + if (isset($map[$key])) { + throw new Exception( + pht( + 'Workflow ("%s") generates two prompts with the same '. + 'key ("%s"). Each prompt a workflow generates must have a '. + 'unique key.', + get_class($this), + $key)); + } + + $map[$key] = $prompt; + } + + $this->promptMap = $map; + } + + return $this->promptMap; + } + + protected function getPrompt($key) { + $map = $this->getPromptMap(); + + $prompt = idx($map, $key); + if (!$prompt) { + throw new Exception( + pht( + 'Workflow ("%s") is requesting a prompt ("%s") but it did not '. + 'generate any prompt with that name in "newPrompts()".', + get_class($this), + $key)); + } + + return clone $prompt; + } + } diff --git a/support/shell/hooks/bash-completion.sh b/support/shell/hooks/bash-completion.sh index edf34f7e..4d4888ea 100644 --- a/support/shell/hooks/bash-completion.sh +++ b/support/shell/hooks/bash-completion.sh @@ -1,9 +1,10 @@ SCRIPTDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" > /dev/null && pwd )" +GENERATED_RULES_FILE="${SCRIPTDIR}/../rules/bash-rules.sh" # Try to generate the shell completion rules if they do not yet exist. -if [ ! -f "${SCRIPTDIR}/bash-rules.sh" ]; then +if [ ! -f "${GENERATED_RULES_FILE}" ]; then arc shell-complete --generate >/dev/null 2>/dev/null fi; # Source the shell completion rules. -source "${SCRIPTDIR}/../rules/bash-rules.sh" +source "${GENERATED_RULES_FILE}"