summaryrefslogtreecommitdiffstats
path: root/3rdparty/simpletest/arguments.php
blob: 89e7f9de6ef276651c834c97a9e6d3fb39998cf7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
<?php
/**
 *  base include file for SimpleTest
 *  @package    SimpleTest
 *  @subpackage UnitTester
 *  @version    $Id: dumper.php 1909 2009-07-29 15:58:11Z dgheath $
 */

/**
 *    Parses the command line arguments.
 *    @package  SimpleTest
 *    @subpackage   UnitTester
 */
class SimpleArguments {
    private $all = array();

    /**
     * Parses the command line arguments. The usual formats
     * are supported:
     * -f value
     * -f=value
     * --flag=value
     * --flag value
     * -f           (true)
     * --flag       (true)
     * @param array $arguments      Normally the PHP $argv.
     */
    function __construct($arguments) {
        array_shift($arguments);
        while (count($arguments) > 0) {
            list($key, $value) = $this->parseArgument($arguments);
            $this->assign($key, $value);
        }
    }

    /**
     * Sets the value in the argments object. If multiple
     * values are added under the same key, the key will
     * give an array value in the order they were added.
     * @param string $key    The variable to assign to.
     * @param string value   The value that would norally
     *                       be colected on the command line.
     */
    function assign($key, $value) {
        if ($this->$key === false) {
            $this->all[$key] = $value;
        } elseif (! is_array($this->$key)) {
            $this->all[$key] = array($this->$key, $value);
        } else {
            $this->all[$key][] = $value;
        }
    }

    /**
     * Extracts the next key and value from the argument list.
     * @param array $arguments      The remaining arguments to be parsed.
     *                              The argument list will be reduced.
     * @return array                Two item array of key and value.
     *                              If no value can be found it will
     *                              have the value true assigned instead.
     */
    private function parseArgument(&$arguments) {
        $argument = array_shift($arguments);
        if (preg_match('/^-(\w)=(.+)$/', $argument, $matches)) {
            return array($matches[1], $matches[2]);
        } elseif (preg_match('/^-(\w)$/', $argument, $matches)) {
            return array($matches[1], $this->nextNonFlagElseTrue($arguments));
        } elseif (preg_match('/^--(\w+)=(.+)$/', $argument, $matches)) {
            return array($matches[1], $matches[2]);
        } elseif (preg_match('/^--(\w+)$/', $argument, $matches)) {
            return array($matches[1], $this->nextNonFlagElseTrue($arguments));
        }
    }

    /**
     * Attempts to use the next argument as a value. It
     * won't use what it thinks is a flag.
     * @param array $arguments    Remaining arguments to be parsed.
     *                            This variable is modified if there
     *                            is a value to be extracted.
     * @return string/boolean     The next value unless it's a flag.
     */
    private function nextNonFlagElseTrue(&$arguments) {
        return $this->valueIsNext($arguments) ? array_shift($arguments) : true;
    }

    /**
     * Test to see if the next available argument is a valid value.
     * If it starts with "-" or "--" it's a flag and doesn't count.
     * @param array $arguments    Remaining arguments to be parsed.
     *                            Not affected by this call.
     * boolean                    True if valid value.
     */
    function valueIsNext($arguments) {
        return isset($arguments[0]) && ! $this->isFlag($arguments[0]);
    }

    /**
     * It's a flag if it starts with "-" or "--".
     * @param string $argument       Value to be tested.
     * @return boolean               True if it's a flag.
     */
    function isFlag($argument) {
        return strncmp($argument, '-', 1) == 0;
    }

    /**
     * The arguments are available as individual member
     * variables on the object.
     * @param string $key              Argument name.
     * @return string/array/boolean    Either false for no value,
     *                                 the value as a string or
     *                                 a list of multiple values if
     *                                 the flag had been specified more
     *                                 than once.
     */
    function __get($key) {
        if (isset($this->all[$key])) {
            return $this->all[$key];
        }
        return false;
    }

    /**
     * The entire argument set as a hash.
     * @return hash         Each argument and it's value(s).
     */
    function all() {
        return $this->all;
    }
}

/**
 *    Renders the help for the command line arguments.
 *    @package  SimpleTest
 *    @subpackage   UnitTester
 */
class SimpleHelp {
    private $overview;
    private $flag_sets = array();
    private $explanations = array();

    /**
     * Sets up the top level explanation for the program.
     * @param string $overview        Summary of program.
     */
    function __construct($overview = '') {
        $this->overview = $overview;
    }

    /**
     * Adds the explanation for a group of flags that all
     * have the same function.
     * @param string/array $flags       Flag and alternates. Don't
     *                                  worry about leading dashes
     *                                  as these are inserted automatically.
     * @param string $explanation       What that flag group does.
     */
    function explainFlag($flags, $explanation) {
        $flags = is_array($flags) ? $flags : array($flags);
        $this->flag_sets[] = $flags;
        $this->explanations[] = $explanation;
    }

    /**
     * Generates the help text.
     * @returns string      The complete formatted text.
     */
    function render() {
        $tab_stop = $this->longestFlag($this->flag_sets) + 4;
        $text = $this->overview . "\n";
        for ($i = 0; $i < count($this->flag_sets); $i++) {
            $text .= $this->renderFlagSet($this->flag_sets[$i], $this->explanations[$i], $tab_stop);
        }
        return $this->noDuplicateNewLines($text);
    }

    /**
     * Works out the longest flag for formatting purposes.
     * @param array $flag_sets      The internal flag set list.
     */
    private function longestFlag($flag_sets) {
        $longest = 0;
        foreach ($flag_sets as $flags) {
            foreach ($flags as $flag) {
                $longest = max($longest, strlen($this->renderFlag($flag)));
            }
        }
        return $longest;
    }

    /**
     * Generates the text for a single flag and it's alternate flags.
     * @returns string           Help text for that flag group.
     */
    private function renderFlagSet($flags, $explanation, $tab_stop) {
        $flag = array_shift($flags);
        $text = str_pad($this->renderFlag($flag), $tab_stop, ' ') . $explanation . "\n";
        foreach ($flags as $flag) {
            $text .= '  ' . $this->renderFlag($flag) . "\n";
        }
        return $text;
    }

    /**
     * Generates the flag name including leading dashes.
     * @param string $flag          Just the name.
     * @returns                     Fag with apropriate dashes.
     */
    private function renderFlag($flag) {
        return (strlen($flag) == 1 ? '-' : '--') . $flag;
    }

    /**
     * Converts multiple new lines into a single new line.
     * Just there to trap accidental duplicate new lines.
     * @param string $text      Text to clean up.
     * @returns string          Text with no blank lines.
     */
    private function noDuplicateNewLines($text) {
        return preg_replace('/(\n+)/', "\n", $text);
    }
}
?>