comparison vendor/psy/psysh/src/Psy/Formatter/DocblockFormatter.php @ 0:4c8ae668cc8c

Initial import (non-working)
author Chris Cannam
date Wed, 29 Nov 2017 16:09:58 +0000
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:4c8ae668cc8c
1 <?php
2
3 /*
4 * This file is part of Psy Shell.
5 *
6 * (c) 2012-2017 Justin Hileman
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12 namespace Psy\Formatter;
13
14 use Psy\Util\Docblock;
15 use Symfony\Component\Console\Formatter\OutputFormatter;
16
17 /**
18 * A pretty-printer for docblocks.
19 */
20 class DocblockFormatter implements Formatter
21 {
22 private static $vectorParamTemplates = array(
23 'type' => 'info',
24 'var' => 'strong',
25 );
26
27 /**
28 * Format a docblock.
29 *
30 * @param \Reflector $reflector
31 *
32 * @return string Formatted docblock
33 */
34 public static function format(\Reflector $reflector)
35 {
36 $docblock = new Docblock($reflector);
37 $chunks = array();
38
39 if (!empty($docblock->desc)) {
40 $chunks[] = '<comment>Description:</comment>';
41 $chunks[] = self::indent(OutputFormatter::escape($docblock->desc), ' ');
42 $chunks[] = '';
43 }
44
45 if (!empty($docblock->tags)) {
46 foreach ($docblock::$vectors as $name => $vector) {
47 if (isset($docblock->tags[$name])) {
48 $chunks[] = sprintf('<comment>%s:</comment>', self::inflect($name));
49 $chunks[] = self::formatVector($vector, $docblock->tags[$name]);
50 $chunks[] = '';
51 }
52 }
53
54 $tags = self::formatTags(array_keys($docblock::$vectors), $docblock->tags);
55 if (!empty($tags)) {
56 $chunks[] = $tags;
57 $chunks[] = '';
58 }
59 }
60
61 return rtrim(implode("\n", $chunks));
62 }
63
64 /**
65 * Format a docblock vector, for example, `@throws`, `@param`, or `@return`.
66 *
67 * @see DocBlock::$vectors
68 *
69 * @param array $vector
70 * @param array $lines
71 *
72 * @return string
73 */
74 private static function formatVector(array $vector, array $lines)
75 {
76 $template = array(' ');
77 foreach ($vector as $type) {
78 $max = 0;
79 foreach ($lines as $line) {
80 $chunk = $line[$type];
81 $cur = empty($chunk) ? 0 : strlen($chunk) + 1;
82 if ($cur > $max) {
83 $max = $cur;
84 }
85 }
86
87 $template[] = self::getVectorParamTemplate($type, $max);
88 }
89 $template = implode(' ', $template);
90
91 return implode("\n", array_map(function ($line) use ($template) {
92 $escaped = array_map(array('Symfony\Component\Console\Formatter\OutputFormatter', 'escape'), $line);
93
94 return rtrim(vsprintf($template, $escaped));
95 }, $lines));
96 }
97
98 /**
99 * Format docblock tags.
100 *
101 * @param array $skip Tags to exclude
102 * @param array $tags Tags to format
103 *
104 * @return string formatted tags
105 */
106 private static function formatTags(array $skip, array $tags)
107 {
108 $chunks = array();
109
110 foreach ($tags as $name => $values) {
111 if (in_array($name, $skip)) {
112 continue;
113 }
114
115 foreach ($values as $value) {
116 $chunks[] = sprintf('<comment>%s%s</comment> %s', self::inflect($name), empty($value) ? '' : ':', OutputFormatter::escape($value));
117 }
118
119 $chunks[] = '';
120 }
121
122 return implode("\n", $chunks);
123 }
124
125 /**
126 * Get a docblock vector template.
127 *
128 * @param string $type Vector type
129 * @param int $max Pad width
130 *
131 * @return string
132 */
133 private static function getVectorParamTemplate($type, $max)
134 {
135 if (!isset(self::$vectorParamTemplates[$type])) {
136 return sprintf('%%-%ds', $max);
137 }
138
139 return sprintf('<%s>%%-%ds</%s>', self::$vectorParamTemplates[$type], $max, self::$vectorParamTemplates[$type]);
140 }
141
142 /**
143 * Indent a string.
144 *
145 * @param string $text String to indent
146 * @param string $indent (default: ' ')
147 *
148 * @return string
149 */
150 private static function indent($text, $indent = ' ')
151 {
152 return $indent . str_replace("\n", "\n" . $indent, $text);
153 }
154
155 /**
156 * Convert underscored or whitespace separated words into sentence case.
157 *
158 * @param string $text
159 *
160 * @return string
161 */
162 private static function inflect($text)
163 {
164 $words = trim(preg_replace('/[\s_-]+/', ' ', preg_replace('/([a-z])([A-Z])/', '$1 $2', $text)));
165
166 return implode(' ', array_map('ucfirst', explode(' ', $words)));
167 }
168 }