Browse Source

Merge pull request #6728 from antograssiot/issue-6719

Add a wrapBlock function to Text
Mark Story 10 years ago
parent
commit
53fdb18655

+ 3 - 3
src/Console/HelpFormatter.php

@@ -76,7 +76,7 @@ class HelpFormatter
             $out[] = '';
             $max = $this->_getMaxLength($subcommands) + 2;
             foreach ($subcommands as $command) {
-                $out[] = Text::wrap($command->help($max), [
+                $out[] = Text::wrapBlock($command->help($max), [
                     'width' => $width,
                     'indent' => str_repeat(' ', $max),
                     'indentAt' => 1
@@ -93,7 +93,7 @@ class HelpFormatter
             $out[] = '<info>Options:</info>';
             $out[] = '';
             foreach ($options as $option) {
-                $out[] = Text::wrap($option->help($max), [
+                $out[] = Text::wrapBlock($option->help($max), [
                     'width' => $width,
                     'indent' => str_repeat(' ', $max),
                     'indentAt' => 1
@@ -108,7 +108,7 @@ class HelpFormatter
             $out[] = '<info>Arguments:</info>';
             $out[] = '';
             foreach ($arguments as $argument) {
-                $out[] = Text::wrap($argument->help($max), [
+                $out[] = Text::wrapBlock($argument->help($max), [
                     'width' => $width,
                     'indent' => str_repeat(' ', $max),
                     'indentAt' => 1

+ 53 - 0
src/Utility/Text.php

@@ -312,6 +312,59 @@ class Text
     }
 
     /**
+     * Wraps a complete block of text to a specific width, can optionally wrap
+     * at word breaks.
+     *
+     * ### Options
+     *
+     * - `width` The width to wrap to. Defaults to 72.
+     * - `wordWrap` Only wrap on words breaks (spaces) Defaults to true.
+     * - `indent` String to indent with. Defaults to null.
+     * - `indentAt` 0 based index to start indenting at. Defaults to 0.
+     *
+     * @param string $text The text to format.
+     * @param array|int $options Array of options to use, or an integer to wrap the text to.
+     * @return string Formatted text.
+     */
+    public static function wrapBlock($text, $options = [])
+    {
+        if (is_numeric($options)) {
+            $options = ['width' => $options];
+        }
+        $options += ['width' => 72, 'wordWrap' => true, 'indent' => null, 'indentAt' => 0];
+
+        if (!empty($options['indentAt']) && $options['indentAt'] === 0) {
+            $indentLength = !empty($options['indent']) ? strlen($options['indent']) : 0;
+            $options['width'] = $options['width'] - $indentLength;
+            return self::wrap($text, $options);
+        }
+
+        $wrapped = self::wrap($text, $options);
+
+        if (!empty($options['indent'])) {
+            $indentationLength = mb_strlen($options['indent']);
+            $chunks = explode("\n", $wrapped);
+            $count = count($chunks);
+            if ($count < 2) {
+                return $wrapped;
+            }
+            $toRewrap = '';
+            for ($i = $options['indentAt']; $i < $count; $i++) {
+                $toRewrap .= mb_substr($chunks[$i], $indentationLength) . ' ';
+                unset($chunks[$i]);
+            }
+            $options['width'] -= $indentationLength;
+            $options['indentAt'] = 0;
+            $rewrapped = self::wrap($toRewrap, $options);
+            $newChunks = explode("\n", $rewrapped);
+
+            $chunks = array_merge($chunks, $newChunks);
+            $wrapped = implode("\n", $chunks);
+        }
+        return $wrapped;
+    }
+
+    /**
      * Unicode and newline aware version of wordwrap.
      *
      * @param string $text The text to format.

+ 6 - 0
tests/TestCase/Console/HelpFormatterTest.php

@@ -155,6 +155,9 @@ txt;
         $parser = new ConsoleOptionParser('mycommand', false);
         $parser->addSubcommand('method', ['help' => 'This is another command'])
             ->addOption('test', ['help' => 'A test option.']);
+        $parser->addSubcommand('plugin', ['help' =>
+            'Create the directory structure, AppController class and testing setup for a new plugin. ' .
+            'Can create plugins in any of your bootstrapped plugin paths.']);
 
         $formatter = new HelpFormatter($parser);
         $result = $formatter->text();
@@ -165,6 +168,9 @@ cake mycommand [subcommand] [-h] [--test]
 <info>Subcommands:</info>
 
 method  This is another command
+plugin  Create the directory structure, AppController class and testing
+        setup for a new plugin. Can create plugins in any of your
+        bootstrapped plugin paths.
 
 To see help on a subcommand use <info>`cake mycommand [subcommand] --help`</info>
 

+ 70 - 0
tests/TestCase/Utility/TextTest.php

@@ -451,6 +451,76 @@ TEXT;
     }
 
     /**
+     * test wrapBlock() indentical to wrap()
+     *
+     * @return void
+     */
+    public function testWrapBlockIndenticalToWrap()
+    {
+        $text = 'This is the song that never ends. This is the song that never ends. This is the song that never ends.';
+        $result = Text::wrapBlock($text, 33);
+        $expected = Text::wrap($text, 33);
+        $this->assertTextEquals($expected, $result);
+
+        $result = Text::wrapBlock($text, ['width' => 33, 'indentAt' => 0]);
+        $expected = Text::wrap($text, ['width' => 33, 'indentAt' => 0]);
+        $this->assertTextEquals($expected, $result);
+    }
+
+    /**
+     * test wrapBlock() indenting from first line
+     *
+     * @return void
+     */
+    public function testWrapBlockWithIndentAt0()
+    {
+        $text = 'This is the song that never ends. This is the song that never ends. This is the song that never ends.';
+        $result = Text::wrapBlock($text, ['width' => 33, 'indent' => "\t", 'indentAt' => 0]);
+        $expected = <<<TEXT
+	This is the song that never
+	ends. This is the song that
+	never ends. This is the song
+	that never ends.
+TEXT;
+        $this->assertTextEquals($expected, $result);
+    }
+
+    /**
+     * test wrapBlock() indenting from second line
+     *
+     * @return void
+     */
+    public function testWrapBlockWithIndentAt1()
+    {
+        $text = 'This is the song that never ends. This is the song that never ends. This is the song that never ends.';
+        $result = Text::wrapBlock($text, ['width' => 33, 'indent' => "\t", 'indentAt' => 1]);
+        $expected = <<<TEXT
+This is the song that never ends.
+	This is the song that never
+	ends. This is the song that
+	never ends.
+TEXT;
+        $this->assertTextEquals($expected, $result);
+    }
+
+    /**
+     * test wrapBlock() indenting with multibyte caracters
+     *
+     * @return void
+     */
+    public function testWrapBlockIndentWithMultibyte()
+    {
+        $text = 'This is the song that never ends. 这是永远不会结束的歌曲。 This is the song that never ends.';
+        $result = Text::wrapBlock($text, ['width' => 33, 'indent' => " → ", 'indentAt' => 1]);
+        $expected = <<<TEXT
+This is the song that never ends.
+ → 这是永远不会结束的歌曲。 This is the song
+ → that never ends.
+TEXT;
+        $this->assertTextEquals($expected, $result);
+    }
+
+    /**
      * testTruncate method
      *
      * @return void