PageRenderTime 48ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/codeformatter/lib/phpbeautifier/DocBlockGenerator/GetoptPlus.php

https://github.com/bibibaonam/sublimetext-codeformatter
PHP | 430 lines | 155 code | 38 blank | 237 comment | 14 complexity | 0a44ee4ee4534a770ec8667819f5b429 MD5 | raw file
  1. <?php
  2. /**
  3. * DocBlock Generator
  4. *
  5. * PHP version 5
  6. *
  7. * All rights reserved.
  8. * Redistribution and use in source and binary forms, with or without modification,
  9. * are permitted provided that the following conditions are met:
  10. * + Redistributions of source code must retain the above copyright notice,
  11. * this list of conditions and the following disclaimer.
  12. * + Redistributions in binary form must reproduce the above copyright notice,
  13. * this list of conditions and the following disclaimer in the documentation and/or
  14. * other materials provided with the distribution.
  15. * + The names of its contributors may not be used to endorse or
  16. * promote products derived from this software without specific prior written permission.
  17. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  18. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  19. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  20. * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  21. * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  22. * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  23. * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  24. * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  25. * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  26. * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  27. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  28. *
  29. * @category PHP
  30. * @package PHP_DocBlockGenerator
  31. * @author Michel Corne <mcorne@yahoo.com>
  32. * @copyright 2007 Michel Corne
  33. * @license http://www.opensource.org/licenses/bsd-license.php The BSD License
  34. * @version SVN: $Id: GetoptPlus.php 30 2007-07-23 16:46:42Z mcorne $
  35. * @link http://pear.php.net/package/PHP_DocBlockGenerator
  36. */
  37. require_once 'Console/Getopt.php';
  38. /**
  39. * Getopt extension
  40. *
  41. * Generate short options, long options, usage/help automaticly
  42. *
  43. * @category PHP
  44. * @package PHP_DocBlockGenerator
  45. * @author Michel Corne <mcorne@yahoo.com>
  46. * @copyright 2007 Michel Corne
  47. * @license http://www.opensource.org/licenses/bsd-license.php The BSD License
  48. * @version Release: @package_version@
  49. * @link http://pear.php.net/package/PHP_DocBlockGenerator
  50. */
  51. class PHP_DocBlockGenerator_GetoptPlus
  52. {
  53. /**
  54. * The option name padding within the option descrition
  55. */
  56. const optionPadding = 30;
  57. /**
  58. * The options section title
  59. */
  60. const options = 'Options: ';
  61. /**
  62. * The parameter section title
  63. */
  64. const parameters = 'Parameters: ';
  65. /**
  66. * The usage section title
  67. */
  68. const usage = 'Usage: ';
  69. /**
  70. * The configuration sub-array keys
  71. *
  72. * @var array
  73. * @access private
  74. */
  75. private $configKeys = array('usage', 'header', 'options', 'parameters', 'footer');
  76. /**
  77. * The help option description
  78. *
  79. * @var array
  80. * @access private
  81. */
  82. private $help = array(array('h', 'help', '', 'This help.'));
  83. /**
  84. * The long options used by Console_Getopt::doGetopt()
  85. *
  86. * @var array
  87. * @access private
  88. */
  89. private $longOptions = array();
  90. /**
  91. * The short options used by Console_Getopt::doGetopt()
  92. *
  93. * @var string
  94. * @access private
  95. */
  96. private $shortOptions = '';
  97. /**
  98. * The short name to long option name cross-references
  99. *
  100. * @var array
  101. * @access private
  102. */
  103. private $short2long = array();
  104. /**
  105. * The long name to short option name cross-references
  106. *
  107. * @var array
  108. * @access private
  109. */
  110. private $long2short = array();
  111. /**
  112. * Align a set of lines
  113. *
  114. * Additional data is added to the first line.
  115. * The other lines are padded and aligned to the first one.
  116. *
  117. * @param array $lines the set of lines
  118. * @param string $firstLineAddon the additional data to add to the first line
  119. * @param integer $paddingLength the padding length
  120. * @return array the aligned lines
  121. * @access public
  122. */
  123. public function alignLines($lines, $firstLineAddon, $paddingLength = 0)
  124. {
  125. // defaults the left alignment to the length of the additional information
  126. $paddingLength or $firstLineAddon and $paddingLength = strlen($firstLineAddon) + 1;
  127. if ($paddingLength > strlen($firstLineAddon)) {
  128. // pads the additional data and adds it to the left of the first line
  129. $firstLineAddon = str_pad($firstLineAddon, $paddingLength);
  130. $firstLine = $firstLineAddon . array_shift($lines);
  131. } else {
  132. // the information on the left is longer than the padding size
  133. $firstLine = $firstLineAddon;
  134. }
  135. // left pads the other lines
  136. $padding = str_repeat(' ', $paddingLength);
  137. $callback = create_function('$string', "return '$padding' . \$string;");
  138. $lines = array_map($callback, $lines);
  139. // restores the first line
  140. array_unshift($lines, $firstLine);
  141. return $lines;
  142. }
  143. /**
  144. * Gets the options and parameters from the command arguments
  145. *
  146. * Extracts the command arguments. Tidies the options.
  147. * Builds the help/usage text.
  148. *
  149. * @param array $config the command configuration
  150. * @param boolean $toLongNames Converts options names to long names if true,
  151. * e.g. "align", or to short names if false,
  152. * e.g. "A", default is true
  153. * @param boolean $asKeys return options with the names used as array
  154. * keys if true, or leave them as returned by
  155. * Console_Getopt::doGetopt(), default is true
  156. * @param integer $version Console_Getopt::doGetopt version
  157. * @return array the options and parameters
  158. * @access public
  159. * @static
  160. */
  161. public static function getopt($config = array(), $toLongNames = true, $asKeys = true, $version = 2)
  162. {
  163. $getopt = new self;
  164. // silently ignore invalid configuration arrays, defaults the absent ones to empty arrays
  165. $default = array_combine($getopt->configKeys, array_fill(0, count($getopt->configKeys), array()));
  166. $config = array_intersect_key($config, $default);
  167. $config = array_merge($default, $config);
  168. // extracts the command arguments, including the command name
  169. $args = Console_Getopt::readPHPArgv();
  170. $command = array_shift($args);
  171. // tidies the options, sets the short and long options, and calls getopt
  172. $config['options'] = $getopt->tidyOptions($config['options']);
  173. $options = Console_Getopt::doGetopt($version, $args, $getopt->shortOptions, $getopt->longOptions);
  174. // a syntax error, prints out the error message
  175. PEAR::isError($options) and exit($options->getMessage());
  176. // tidies the arguments
  177. $options[0] = $getopt->tidyArgs($options[0], $toLongNames, $asKeys);
  178. // a request for help/usage, prints the command usage
  179. $options[0] == 'help' and exit(implode("\n", $getopt->setHelp($config, $command)));
  180. return $options;
  181. }
  182. /**
  183. * Set the help/usage text
  184. *
  185. * @param array $config the command configuration
  186. * @param string $command the command name
  187. * @return array the help/usage text
  188. * @access public
  189. */
  190. public function setHelp($config, $command)
  191. {
  192. // sets all the help/usage section texts
  193. $config['parameters'] = $this->alignLines($config['parameters'], self::parameters) ;
  194. $config['usage'] = $this->setUsage($config['usage'], $command, $config['options'], $config['parameters']);
  195. $config['options'] = $this->setOptions($config['options']);
  196. $config['header'] = $this->tidyArray($config['header']);
  197. $config['footer'] = $this->tidyArray($config['footer']);
  198. // merges the section texts together
  199. $callback = create_function('$array, $array1', '$array or $array = array(); return array_merge($array, $array1);');
  200. $help = array_reduce($config, $callback, array());
  201. return $help;
  202. }
  203. /**
  204. * Sets the options help text section
  205. *
  206. * @param array $options the options descriptions
  207. * @return array the options help text section
  208. * @access public
  209. */
  210. public function setOptions($options)
  211. {
  212. $padding = str_repeat(' ', self::optionPadding);
  213. $callback = create_function('$string', "return '$padding' . \$string;");
  214. $lines = array();
  215. foreach($options as $option) {
  216. // expecting tidy options
  217. list($shortName, $longName, $condition, $desc) = $option;
  218. // extracts the option example value from the description
  219. // encloses with angle/square brackets if mandatory/optional
  220. $condition == ':' and $value = '<' . array_shift($desc) . '>' or
  221. $condition == '::' and $value = '[' . array_shift($desc) . ']' or
  222. $value = '';
  223. // sets the option names
  224. $optionNames = array();
  225. $shortName and $optionNames[] = "-$shortName";
  226. $longName and $optionNames[] = "--$longName";
  227. $value and $optionNames[] = $value;
  228. $optionNames = implode(' ', $optionNames);
  229. // adds the option names to the description
  230. $desc = $this->alignLines($desc, $optionNames, self::optionPadding);
  231. $lines = array_merge($lines, $desc);
  232. }
  233. // prefix the options with e.g. "Options:"
  234. $lines and array_unshift($lines, self::options);
  235. return $lines;
  236. }
  237. /**
  238. * Sets the usage help text section
  239. *
  240. * @param array $usages the usages descriptions
  241. * @param string $command the command name
  242. * @param array $options the options descriptions
  243. * @param array $parameters the parameters descriptions
  244. * @return array the usage help text section
  245. * @access public
  246. */
  247. public function setUsage($usages, $command, $options, $parameters)
  248. {
  249. if (empty($usages)) {
  250. // usage is empty, defaults to a one line usage, e.g. [options] [parameters]
  251. empty($options) or $usages[] = '[options]';
  252. empty($parameters) or $usages[] = '[parameters]';
  253. $usages = implode(' ', $usages);
  254. }
  255. // expecting an array of arrays of usage lines, or possibly a single usage line,
  256. is_array($usages) or $usages = array($usages);
  257. $lines = array();
  258. $padding = str_repeat(' ', strlen(self::usage));
  259. foreach($usages as $idx => $usage) {
  260. $usage = $this->tidyArray($usage);
  261. // adds the usage keywork to the first usage, e.g. "Usage:"
  262. $prefix = $idx? $padding : self::usage;
  263. // adds the command to each usage, e.g. command [options] [parameters]
  264. $prefix .= basename($command);
  265. $usage = $this->alignLines($usage, $prefix);
  266. $lines = array_merge($lines, $usage);
  267. }
  268. return $lines;
  269. }
  270. /**
  271. * Tidies the command arguments
  272. *
  273. * @param array $options the options arguments
  274. * @param boolean $toLongNames Converts options names to long names if true,
  275. * e.g. "align", or to short names if false,
  276. * e.g. "A", default is true
  277. * @param boolean $asKeys return options with the names used as array
  278. * keys if true, or leave them as returned by
  279. * Console_Getopt::doGetopt(), default is true
  280. * @return array the tidy options arguments
  281. * @access public
  282. */
  283. public function tidyArgs($options, $toLongNames = true, $asKeys = true)
  284. {
  285. $tidied = array();
  286. foreach($options as $option) {
  287. // extracs the argument name and value
  288. list($name, $value) = $option;
  289. // removes the "--" prefix from long arguments
  290. $isLongName = substr($name, 0, 2) == '--' and $name = substr($name, 2);
  291. if (in_array($name, array('h', 'help'))) {
  292. // the help/usage option
  293. return 'help';
  294. }
  295. if ($toLongNames) {
  296. // changes all argument names to long names
  297. isset($this->short2long[$name]) and $name = $this->short2long[$name];
  298. } else {
  299. // changes all argument names to short names
  300. isset($this->long2short[$name]) and $name = $this->long2short[$name];
  301. }
  302. if ($asKeys) {
  303. // converts the arguments to an associative array with the argument name as the key
  304. $tidied[$name] = is_null($value)? '' : $value;
  305. } else {
  306. // leaves the arguments as per the Console_Getopt::doGetopt() format
  307. $tidied[] = array($name, $value);
  308. }
  309. }
  310. return $tidied;
  311. }
  312. /**
  313. * Tidies an array
  314. *
  315. * Makes an array if passed as a string.
  316. * Optionally forces the values to strings if there are not.
  317. *
  318. * @param array $array the array
  319. * @param boolean $tidyString forces the values to string if true,
  320. * or leave them untouched if false
  321. * @return array the tidy array
  322. * @access public
  323. */
  324. public function tidyArray($array, $tidyString = true)
  325. {
  326. // if not an array converts to an array
  327. is_array($array) or $array = array($array);
  328. // tidies the array string values
  329. $tidyString and $array = array_map(array($this, 'tidyString'), $array);
  330. return $array;
  331. }
  332. /**
  333. * Tydies the options
  334. *
  335. * @param array $options the options descriptions
  336. * @return array the tidy options
  337. * @access public
  338. */
  339. public function tidyOptions($options)
  340. {
  341. // expecting an array of arrays of option settings, or possibly a single option short name,
  342. // or possibly a single option settings
  343. is_array($options) or $options = array($options);
  344. is_array(current($options)) or $options = array($options);
  345. // adds the default help/usage option
  346. $options = array_merge($options, $this->help);
  347. $tidied = array();
  348. foreach($options as $option) {
  349. $option = $this->tidyArray($option, false);
  350. // extracts the first letter of the option short name, ignores the others letters silently
  351. $shortName = $this->tidyString(current($option)) and $shortName = $shortName{0};
  352. // extracts the option long name
  353. $longName = $this->tidyString(next($option));
  354. if ($shortName and $longName) {
  355. // extracts the condition, silently ignores conditions different from ":" and "::"
  356. $condition = $this->tidyString(next($option));
  357. in_array($condition, array(':', '::')) or $condition = '';
  358. // extracts the description
  359. $desc = $this->tidyArray(next($option));
  360. // adds to the tidy options
  361. $tidied[] = array($shortName, $longName, $condition, $desc);
  362. // builds the short and long options lists used by Console_Getopt::doGetopt()
  363. $this->shortOptions .= $shortName . $condition;
  364. $this->longOptions[] = $longName . str_replace(':', '=', $condition);
  365. // creates cross-references between short and long option names
  366. if ($shortName and $longName) {
  367. $this->short2long[$shortName] = $longName; // check that there is no duplicates !!!
  368. $this->long2short[$longName] = $shortName;
  369. }
  370. }
  371. // else: silently ignores empty option names
  372. }
  373. return $tidied;
  374. }
  375. /**
  376. * Tidies a string
  377. *
  378. * Retains only the first value if passed as an array.
  379. *
  380. * @param string $string the string
  381. * @return string the tidy string
  382. * @access public
  383. */
  384. public function tidyString($string)
  385. {
  386. // if an array: captures the first value and converts it to a string
  387. // silently ignores the other values
  388. is_array($string) and $string = current($string);
  389. return trim($string);
  390. }
  391. }
  392. ?>