Subversion-Projekte lars-tiefland.php_share

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
1 lars 1
<?php
2
 
3
/**
4
 * Console GetoptPlus/Help
5
 *
6
 * PHP version 5
7
 *
8
 * All rights reserved.
9
 * Redistribution and use in source and binary forms, with or without modification,
10
 * are permitted provided that the following conditions are met:
11
 * + Redistributions of source code must retain the above copyright notice,
12
 * this list of conditions and the following disclaimer.
13
 * + Redistributions in binary form must reproduce the above copyright notice,
14
 * this list of conditions and the following disclaimer in the documentation and/or
15
 * other materials provided with the distribution.
16
 * + The names of its contributors may not be used to endorse or promote
17
 * products derived from this software without specific prior written permission.
18
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
22
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
25
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
26
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
27
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
 *
30
 * @category  Console
31
 * @package   Console_GetoptPlus
32
 * @author    Michel Corne <mcorne@yahoo.com>
33
 * @copyright 2008 Michel Corne
34
 * @license   http://www.opensource.org/licenses/bsd-license.php The BSD License
35
 * @version   SVN: $Id: Help.php 47 2008-01-10 11:03:38Z mcorne $
36
 * @link      http://pear.php.net/package/Console_GetoptPlus
37
 */
38
 
39
/**
40
 * Generation of the command usage/help
41
 *
42
 * @category  Console
43
 * @package   Console_GetoptPlus
44
 * @author    Michel Corne <mcorne@yahoo.com>
45
 * @copyright 2008 Michel Corne
46
 * @license   http://www.opensource.org/licenses/bsd-license.php The BSD License
47
 * @version   Release:@package_version@
48
 * @link      http://pear.php.net/package/Console_GetoptPlus
49
 */
50
class Console_GetoptPlus_Help
51
{
52
    /**
53
     * The option name padding within the option descrition
54
     */
55
    const optionPadding = 30;
56
 
57
    /**
58
     * The options section title
59
     */
60
    const options = 'Options:';
61
 
62
    /**
63
     * The parameter section title
64
     */
65
    const parameters = 'Parameters:';
66
 
67
    /**
68
     * The usage section title
69
     */
70
    const usage = 'Usage: ';
71
 
72
    /**
73
     * Aligns a set of lines
74
     *
75
     * Additional data is added to the first line.
76
     * The other lines are padded and aligned to the first one.
77
     *
78
     * @param  array   $lines         the set of lines
79
     * @param  string  $addon         the additional data to add to the first line
80
     * @param  integer $paddingLength the padding length
81
     * @return array   the aligned lines
82
     * @access public
83
     */
84
    public function alignLines($lines, $addon = '', $paddingLength = null)
85
    {
86
        settype($lines, 'array');
87
        settype($addon, 'string');
88
        // defaults the left alignment to the length of the additional data + 1
89
        is_null($paddingLength) and $paddingLength = $addon? (strlen($addon) + 1) : 0;
90
        // extracts the first line
91
        $firstLine = (string)current($lines);
92
        $firstLineEmpty = $firstLine == '';
93
 
94
        if (!$addon or $firstLineEmpty or $paddingLength > strlen($addon)) {
95
            // no addon or padding larger than addon
96
            // pads the additional data and adds it to the left of the first line
97
            $addon = str_pad($addon, $paddingLength);
98
            $firstLine = $addon . array_shift($lines);
99
        } else {
100
            // the information on the left is longer than the padding size
101
            $firstLine = $addon;
102
        }
103
        // left-pads the other lines
104
        $padding = str_repeat(' ', $paddingLength);
105
        $callback = create_function('$string', "return '$padding' . \$string;");
106
        $lines = array_map($callback, $lines);
107
        // prepends the first line
108
        $firstLine = rtrim($firstLine);
109
        array_unshift($lines, $firstLine);
110
 
111
        return $lines;
112
    }
113
 
114
    public static function get($config, $command)
115
    {
116
        $help = new self;
117
        return $help->set($config, $command);
118
    }
119
 
120
    /**
121
     * Creates the help/usage text
122
     *
123
     * @param  array  $config  the command configuration
124
     * @param  string $command the command name
125
     * @return string the help/usage text
126
     * @access public
127
     */
128
    public function set($config, $command)
129
    {
130
        // sets all the help/usage section texts
131
        $help = array();
132
        isset($config['header']) and
133
        $help[] = $this->tidyArray($config['header']);
134
        $help[] = $this->setUsage($config, $command);
135
        isset($config['options']) and $help[] = $this->setOptions($config['options']);
136
        isset($config['parameters']) and
137
        $help[] = $this->alignLines($config['parameters'], self::parameters) ;
138
        isset($config['footer']) and $help[] = $this->tidyArray($config['footer']);
139
        // merges the section texts together
140
        $callback = create_function('$array, $array1',
141
            '$array or $array = array(); return array_merge($array, $array1);');
142
        $help = array_reduce($help, $callback, array());
143
 
144
        return implode("\n", $help);
145
    }
146
 
147
    /**
148
     * Creates the options help text section
149
     *
150
     * @param  array  $optionsConfig the options descriptions
151
     * @return array  the options help text section
152
     * @access public
153
     */
154
    public function setOptions($optionsConfig)
155
    {
156
        settype($optionsConfig, 'array');
157
 
158
        $padding = str_repeat(' ', self::optionPadding);
159
        $callback = create_function('$string', "return '$padding' . \$string;");
160
 
161
        $lines = array();
162
        foreach($optionsConfig as $option) {
163
            $desc = isset($option['desc'])? $option['desc']: '';
164
            settype($desc, 'array');
165
            // extracts the option example value from the description
166
            // encloses with angle/square brackets if mandatory/optional
167
            $value = '';
168
            empty($option['type']) or
169
            $option['type'] == 'mandatory' and $value = '<' . array_shift($desc) . '>' or
170
            $option['type'] == 'optional' and $value = '[' . array_shift($desc) . ']';
171
            // sets the option names
172
            $optionNames = array();
173
            isset($option['short']) and $optionNames[] = "-{$option['short']}";
174
            isset($option['long']) and $optionNames[] = "--{$option['long']}";
175
            $value and $optionNames[] = $value;
176
            $optionNames = implode(' ', $optionNames);
177
            // adds the option names to the description
178
            $desc = $this->alignLines($desc, $optionNames, self::optionPadding);
179
            $lines = array_merge($lines, $desc);
180
        }
181
        // prefix the options with e.g. "Options:"
182
        $lines and array_unshift($lines, self::options);
183
 
184
        return $lines;
185
    }
186
 
187
    /**
188
     * Creates the usage help text section
189
     *
190
     * @param  array  $usages        the usage descriptions
191
     * @param  string $command       the command name
192
     * @param  array  $optionsConfig the options descriptions
193
     * @param  array  $paramsConfig  the parameters descriptions
194
     * @return array  the usage help text section
195
     * @access public
196
     */
197
    public function setUsage($config, $command)
198
    {
199
        if (empty($config['usage'])) {
200
            // usage is empty, defaults to a one line usage,
201
            // e.g. [options] [parameters]
202
            $usage = array();
203
            empty($config['options']) or $usage[] = '[options]';
204
            empty($config['parameters']) or $usage[] = '[parameters]';
205
            $config['usage'] = implode(' ', $usage);
206
        }
207
        // expecting an array of arrays of usage lines,
208
        // or possibly a single usage line
209
        settype($config['usage'], 'array');
210
        $lines = array();
211
        $padding = str_repeat(' ', strlen(self::usage));
212
 
213
        foreach($config['usage'] as $idx => $usage) {
214
            $usage = $this->tidyArray($usage);
215
            // adds the usage keywork to the first usage, e.g. "Usage:"
216
            $prefix = $idx? $padding : self::usage;
217
            // adds the command to each usage, e.g. command [options] [parameters]
218
            $prefix .= basename($command);
219
            $usage = $this->alignLines($usage, $prefix);
220
            $lines = array_merge($lines, $usage);
221
        }
222
 
223
        return $lines;
224
    }
225
 
226
    /**
227
     * Tidies an array
228
     *
229
     * Makes an array if passed as a string.
230
     * Optionally forces the values to strings if there are not.
231
     *
232
     * @param  array   $array      the array
233
     * @param  boolean $tidyString forces the values to string if true,
234
     *                             or leaves them untouched if false
235
     * @return array   the tidied array
236
     * @access public
237
     */
238
    public function tidyArray($array, $tidyString = true)
239
    {
240
        settype($array, 'array');
241
        // tidies the array string values
242
        $tidyString and $array = array_map(array($this, 'tidyString'), $array);
243
 
244
        return $array;
245
    }
246
 
247
    /**
248
     * Tidies a string
249
     *
250
     * Retains only the first value if passed as an array.
251
     *
252
     * @param  string $string the string
253
     * @return string the tidy string
254
     * @access public
255
     */
256
    public function tidyString($string)
257
    {
258
        // if an array: captures the first value and converts it to a string
259
        // silently ignores the other values
260
        is_array($string) and $string = current($string);
261
 
262
        return trim($string);
263
    }
264
}
265
 
266
?>