1: <?php
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: abstract class Horde_Argv_HelpFormatter
59: {
60: const NO_DEFAULT_VALUE = 'none';
61:
62: public $parser = null;
63:
64: public function __construct($indent_increment, $max_help_position,
65: $width = null, $short_first = false)
66: {
67: $this->indent_increment = $indent_increment;
68: $this->help_position = $this->max_help_position = $max_help_position;
69: if (is_null($width)) {
70: if (!empty($_ENV['COLUMNS'])) {
71: $width = $_ENV['COLUMNS'];
72: } else {
73: $width = 80;
74: }
75: $width -= 2;
76: }
77: $this->width = $width;
78: $this->current_indent = 0;
79: $this->level = 0;
80: $this->help_width = null;
81: $this->short_first = $short_first;
82: $this->default_tag = "%default";
83: $this->option_strings = array();
84: $this->_short_opt_fmt = "%s %s";
85: $this->_long_opt_fmt = "%s=%s";
86: }
87:
88: public function setParser($parser)
89: {
90: $this->parser = $parser;
91: }
92:
93: public function setShortOptDelimiter($delim)
94: {
95: if (!in_array($delim, array('', ' '))) {
96: throw new InvalidArgumentException('invalid metavar delimiter for short options: ' . $delim);
97: }
98: $this->_short_opt_fmt = "%s$delim%s";
99: }
100:
101: public function setLongOptDelimiter($delim)
102: {
103: if (!in_array($delim, array('=', ' '))) {
104: throw new InvalidArgumentException('invalid metavar delimiter for long options: ' . $delim);
105: }
106: $this->_long_opt_fmt = "%s$delim%s";
107: }
108:
109: public function indent()
110: {
111: $this->current_indent += $this->indent_increment;
112: $this->level += 1;
113: }
114:
115: public function dedent()
116: {
117: $this->current_indent -= $this->indent_increment;
118: assert($this->current_indent >= 0);
119: $this->level -= 1;
120: }
121:
122: public abstract function formatUsage($usage);
123:
124: public abstract function formatHeading($heading);
125:
126: 127: 128: 129:
130: protected function _formatText($text)
131: {
132: $text_width = $this->width - $this->current_indent;
133: $indent = str_repeat(' ', $this->current_indent);
134: return wordwrap($indent . $text, $text_width, "\n" . $indent);
135: }
136:
137: public function formatDescription($description)
138: {
139: if ($description) {
140: return $this->_formatText($description) . "\n";
141: } else {
142: return '';
143: }
144: }
145:
146: public function formatEpilog($epilog)
147: {
148: if ($epilog) {
149: return "\n" . $this->_formatText($epilog) . "\n";
150: } else {
151: return '';
152: }
153: }
154:
155: public function expandDefault($option)
156: {
157: if (is_null($this->parser) || !$this->default_tag) {
158: return $option->help;
159: }
160:
161: $default_value = isset($this->parser->defaults[$option->dest]) ? $this->parser->defaults[$option->dest] : null;
162: if ($default_value == Horde_Argv_Option::$NO_DEFAULT || !$default_value) {
163: $default_value = self::NO_DEFAULT_VALUE;
164: }
165:
166: return str_replace($this->default_tag, (string)$default_value, $option->help);
167: }
168:
169: 170: 171: 172: 173: 174: 175: 176: 177: 178: 179: 180: 181: 182: 183: 184:
185: public function formatOption($option)
186: {
187: $result = array();
188: $opts = isset($this->option_strings[(string)$option]) ? $this->option_strings[(string)$option] : null;
189: $opt_width = $this->help_position - $this->current_indent - 2;
190: if (strlen($opts) > $opt_width) {
191: $opts = sprintf('%' . $this->current_indent . "s%s\n", "", $opts);
192: $indent_first = $this->help_position;
193: } else {
194:
195: $opts = sprintf("%" . $this->current_indent . "s%-" . $opt_width . "s ", "", $opts);
196: $indent_first = 0;
197: }
198: $result[] = $opts;
199: if ($option->help) {
200: $help_text = $this->expandDefault($option);
201: $help_lines = explode("\n", wordwrap($help_text, $this->help_width));
202: $result[] = sprintf("%" . $indent_first . "s%s\n", '', $help_lines[0]);
203: for ($i = 1, $i_max = count($help_lines); $i < $i_max; $i++) {
204: $result[] = sprintf("%" . $this->help_position . "s%s\n", "", $help_lines[$i]);
205: }
206: } elseif (substr($opts, -1) != "\n") {
207: $result[] = "\n";
208: }
209: return implode('', $result);
210: }
211:
212: public function storeOptionStrings($parser)
213: {
214: $this->indent();
215: $max_len = 0;
216: foreach ($parser->optionList as $opt) {
217: $strings = $this->formatOptionStrings($opt);
218: $this->option_strings[(string)$opt] = $strings;
219: $max_len = max($max_len, strlen($strings) + $this->current_indent);
220: }
221: $this->indent();
222: foreach ($parser->optionGroups as $group) {
223: foreach ($group->optionList as $opt) {
224: $strings = $this->formatOptionStrings($opt);
225: $this->option_strings[(string)$opt] = $strings;
226: $max_len = max($max_len, strlen($strings) + $this->current_indent);
227: }
228: }
229: $this->dedent();
230: $this->dedent();
231: $this->help_position = min($max_len + 2, $this->max_help_position);
232: $this->help_width = $this->width - $this->help_position;
233: }
234:
235: 236: 237:
238: public function formatOptionStrings($option)
239: {
240: if ($option->takesValue()) {
241: $metavar = $option->metavar ? $option->metavar : strtoupper($option->dest);
242: $short_opts = array();
243: foreach ($option->shortOpts as $sopt) {
244: $short_opts[] = sprintf($this->_short_opt_fmt, $sopt, $metavar);
245: }
246: $long_opts = array();
247: foreach ($option->longOpts as $lopt) {
248: $long_opts[] = sprintf($this->_long_opt_fmt, $lopt, $metavar);
249: }
250: } else {
251: $short_opts = $option->shortOpts;
252: $long_opts = $option->longOpts;
253: }
254:
255: if ($this->short_first) {
256: $opts = array_merge($short_opts, $long_opts);
257: } else {
258: $opts = array_merge($long_opts, $short_opts);
259: }
260:
261: return implode(', ', $opts);
262: }
263:
264: }
265: