@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Add static errors, supported protocols, and a dynamic function listing to external editor settings page

Summary:
Ref T13515.

- Previously valid editor URIs may become invalid without being changed (if an administrator removes a protocol from the list, for example), but this isn't explained very well. Show an error on the settings page if the current value isn't usable.
- Generate a list of functions from an authority in the parser.
- Generate a list of protocols from configuration.

Test Plan: {F7370872}

Maniphest Tasks: T13515

Differential Revision: https://secure.phabricator.com/D21146

+214 -24
+28 -2
src/applications/settings/editor/PhabricatorSettingsEditEngine.php
··· 7 7 8 8 private $isSelfEdit; 9 9 private $profileURI; 10 + private $settingsPanel; 10 11 11 12 public function setIsSelfEdit($is_self_edit) { 12 13 $this->isSelfEdit = $is_self_edit; ··· 24 25 25 26 public function getProfileURI() { 26 27 return $this->profileURI; 28 + } 29 + 30 + public function setSettingsPanel($settings_panel) { 31 + $this->settingsPanel = $settings_panel; 32 + return $this; 33 + } 34 + 35 + public function getSettingsPanel() { 36 + return $this->settingsPanel; 27 37 } 28 38 29 39 public function isEngineConfigurable() { ··· 252 262 protected function newEditFormHeadContent( 253 263 PhabricatorEditEnginePageState $state) { 254 264 265 + $content = array(); 266 + 255 267 if ($state->getIsSave()) { 256 - return id(new PHUIInfoView()) 268 + $content[] = id(new PHUIInfoView()) 257 269 ->setSeverity(PHUIInfoView::SEVERITY_NOTICE) 258 270 ->appendChild(pht('Changes saved.')); 259 271 } 260 272 261 - return null; 273 + $panel = $this->getSettingsPanel(); 274 + $content[] = $panel->newSettingsPanelEditFormHeadContent($state); 275 + 276 + return $content; 277 + } 278 + 279 + protected function newEditFormTailContent( 280 + PhabricatorEditEnginePageState $state) { 281 + 282 + $content = array(); 283 + 284 + $panel = $this->getSettingsPanel(); 285 + $content[] = $panel->newSettingsPanelEditFormTailContent($state); 286 + 287 + return $content; 262 288 } 263 289 264 290 }
+11
src/applications/settings/panel/PhabricatorEditEngineSettingsPanel.php
··· 22 22 $engine = id(new PhabricatorSettingsEditEngine()) 23 23 ->setController($this->getController()) 24 24 ->setNavigation($this->getNavigation()) 25 + ->setSettingsPanel($this) 25 26 ->setIsSelfEdit($is_self) 26 27 ->setProfileURI($profile_uri); 27 28 ··· 69 70 } 70 71 71 72 return mpull($panel_settings, 'getSettingKey'); 73 + } 74 + 75 + public function newSettingsPanelEditFormHeadContent( 76 + PhabricatorEditEnginePageState $state) { 77 + return null; 78 + } 79 + 80 + public function newSettingsPanelEditFormTailContent( 81 + PhabricatorEditEnginePageState $state) { 82 + return null; 72 83 } 73 84 74 85 }
+146
src/applications/settings/panel/PhabricatorExternalEditorSettingsPanel.php
··· 21 21 return true; 22 22 } 23 23 24 + public function newSettingsPanelEditFormHeadContent( 25 + PhabricatorEditEnginePageState $state) { 26 + 27 + // The "Editor" setting stored in the database may be invalidated by 28 + // configuration or software changes. If a saved URI becomes invalid 29 + // (for example, its protocol is removed from the list of allowed 30 + // protocols), it will stop working. 31 + 32 + // If the stored value has a problem like this, show a static error 33 + // message without requiring the user to save changes. 34 + 35 + if ($state->getIsSubmit()) { 36 + return null; 37 + } 38 + 39 + $viewer = $this->getViewer(); 40 + $pattern = $viewer->getUserSetting(PhabricatorEditorSetting::SETTINGKEY); 41 + 42 + if (!strlen($pattern)) { 43 + return null; 44 + } 45 + 46 + $caught = null; 47 + try { 48 + id(new PhabricatorEditorURIEngine()) 49 + ->setPattern($pattern) 50 + ->validatePattern(); 51 + } catch (PhabricatorEditorURIParserException $ex) { 52 + $caught = $ex; 53 + } 54 + 55 + if (!$caught) { 56 + return null; 57 + } 58 + 59 + return id(new PHUIInfoView()) 60 + ->setSeverity(PHUIInfoView::SEVERITY_WARNING) 61 + ->appendChild($caught->getMessage()); 62 + } 63 + 64 + public function newSettingsPanelEditFormTailContent( 65 + PhabricatorEditEnginePageState $state) { 66 + $viewer = $this->getViewer(); 67 + 68 + $variables = PhabricatorEditorURIEngine::getVariableDefinitions(); 69 + 70 + $rows = array(); 71 + foreach ($variables as $key => $variable) { 72 + $rows[] = array( 73 + phutil_tag('tt', array(), '%'.$key), 74 + $variable['name'], 75 + $variable['example'], 76 + ); 77 + } 78 + 79 + $table = id(new AphrontTableView($rows)) 80 + ->setHeaders( 81 + array( 82 + pht('Variable'), 83 + pht('Replaced With'), 84 + pht('Example'), 85 + )) 86 + ->setColumnClasses( 87 + array( 88 + 'center', 89 + 'pri', 90 + 'wide', 91 + )); 92 + 93 + $variables_box = id(new PHUIObjectBoxView()) 94 + ->setBackground(PHUIObjectBoxView::WHITE_CONFIG) 95 + ->setHeaderText(pht('External Editor URI Variables')) 96 + ->setTable($table); 97 + 98 + $label_map = array( 99 + 'http' => pht('Hypertext Transfer Protocol'), 100 + 'https' => pht('Hypertext Transfer Protocol over SSL'), 101 + 'txmt' => pht('TextMate'), 102 + 'mvim' => pht('MacVim'), 103 + 'subl' => pht('Sublime Text'), 104 + 'vim' => pht('Vim'), 105 + 'emacs' => pht('Emacs'), 106 + 'vscode' => pht('Visual Studio Code'), 107 + 'editor' => pht('Generic Editor'), 108 + ); 109 + 110 + $default_label = phutil_tag('em', array(), pht('Supported Protocol')); 111 + 112 + $config_key = 'uri.allowed-editor-protocols'; 113 + 114 + $protocols = PhabricatorEnv::getEnvConfig($config_key); 115 + $protocols = array_keys($protocols); 116 + sort($protocols); 117 + 118 + $protocol_rows = array(); 119 + foreach ($protocols as $protocol) { 120 + $label = idx($label_map, $protocol, $default_label); 121 + 122 + $protocol_rows[] = array( 123 + $protocol.'://', 124 + $label, 125 + ); 126 + } 127 + 128 + $protocol_table = id(new AphrontTableView($protocol_rows)) 129 + ->setNoDataString( 130 + pht( 131 + 'Phabricator is not configured to allow any editor protocols.')) 132 + ->setHeaders( 133 + array( 134 + pht('Protocol'), 135 + pht('Description'), 136 + )) 137 + ->setColumnClasses( 138 + array( 139 + 'pri', 140 + 'wide', 141 + )); 142 + 143 + $is_admin = $viewer->getIsAdmin(); 144 + 145 + $configure_button = id(new PHUIButtonView()) 146 + ->setTag('a') 147 + ->setText(pht('View Configuration')) 148 + ->setIcon('fa-sliders') 149 + ->setHref( 150 + urisprintf( 151 + '/config/edit/%s/', 152 + $config_key)) 153 + ->setDisabled(!$is_admin); 154 + 155 + $protocol_header = id(new PHUIHeaderView()) 156 + ->setHeader(pht('Supported Editor Protocols')) 157 + ->addActionLink($configure_button); 158 + 159 + $protocols_box = id(new PHUIObjectBoxView()) 160 + ->setBackground(PHUIObjectBoxView::WHITE_CONFIG) 161 + ->setHeader($protocol_header) 162 + ->setTable($protocol_table); 163 + 164 + return array( 165 + $variables_box, 166 + $protocols_box, 167 + ); 168 + } 169 + 24 170 }
+13 -10
src/applications/settings/setting/PhabricatorEditorSetting.php
··· 20 20 protected function getControlInstructions() { 21 21 return pht( 22 22 "Many text editors can be configured as URI handlers for special ". 23 - "protocols like `editor://`. If you have such an editor, Phabricator ". 24 - "can generate links that you can click to open files locally.". 23 + "protocols like `editor://`. If you have installed and configured ". 24 + "such an editor, Phabricator can generate links that you can click ". 25 + "to open files locally.". 25 26 "\n\n". 26 - "These special variables are supported:". 27 + "Provide a URI pattern for building external editor URIs in your ". 28 + "environment. For example, if you use TextMate on macOS, the pattern ". 29 + "for your machine look like this:". 27 30 "\n\n". 28 - "| Value | Replaced With |\n". 29 - "|-------|---------------|\n". 30 - "| `%%f` | Filename |\n". 31 - "| `%%l` | Line Number |\n". 32 - "| `%%r` | Repository Callsign |\n". 33 - "| `%%%%` | Literal `%%` |\n". 31 + "```name=\"Example: TextMate on macOS\"\n". 32 + "%s\n". 33 + "```\n". 34 34 "\n\n". 35 35 "For complete instructions on editor configuration, ". 36 - "see **[[ %s | %s ]]**.", 36 + "see **[[ %s | %s ]]**.". 37 + "\n\n". 38 + "See the tables below for a list of supported variables and protocols.", 39 + 'txmt://open/?url=file:///Users/alincoln/editor_links/%r/%f&line=%l', 37 40 PhabricatorEnv::getDoclink('User Guide: Configuring an External Editor'), 38 41 pht('User Guide: Configuring an External Editor')); 39 42 }
+12 -12
src/docs/user/userguide/external_editor.diviner
··· 3 3 4 4 Setting up an external editor to integrate with Diffusion and Differential. 5 5 6 - = Overview = 6 + Overview 7 + ======== 7 8 8 9 You can configure a URI handler to allow you to open files from Differential 9 10 and Diffusion in your preferred text editor. 10 11 11 - = Configuring Editors = 12 + Configuring Editors 13 + =================== 12 14 13 15 To configure an external editor, go to {nav Settings > Application Settings > 14 16 External Editor} and set "Editor Link" to a URI pattern (see below). This ··· 17 19 18 20 In general, you'll set this field to something like: 19 21 20 - lang=uri 21 - editor://open/?file=%f 22 - 23 - Some editors support opening multiple files at once when filenames are separated 24 - by spaces. If your editor supports this feature, set "Edit Multiple Files" to 25 - "Supported". Otherwise, you can set it to "Not Supported" to disable "Open All" 26 - buttons in the interface. 22 + ```lang=uri 23 + editor://open/?file=%f 24 + ``` 27 25 28 - == Configuring: TextMate on OS X == 26 + Configuring: TextMate on macOS 27 + ============================== 29 28 30 29 TextMate installs a `txmt://` handler by default, so it's easy to configure 31 30 this feature if you use TextMate. ··· 40 39 41 40 Then set your "Editor Link" to: 42 41 43 - lang=uri 44 - txmt://open/?url=file:///Users/alincoln/editor_links/%r/%f&line=%l 42 + ```lang=uri 43 + txmt://open/?url=file:///Users/alincoln/editor_links/%r/%f&line=%l 44 + ```
+4
src/infrastructure/editor/PhabricatorEditorURIEngine.php
··· 92 92 return array( 93 93 '%' => array( 94 94 'name' => pht('Literal Percent Symbol'), 95 + 'example' => '%', 95 96 ), 96 97 'r' => array( 97 98 'name' => pht('Repository Callsign'), 99 + 'example' => 'XYZ', 98 100 ), 99 101 'f' => array( 100 102 'name' => pht('File Name'), 103 + 'example' => pht('path/to/source.c'), 101 104 ), 102 105 'l' => array( 103 106 'name' => pht('Line Number'), 107 + 'example' => '777', 104 108 ), 105 109 ); 106 110 }