Browse Source

Inflect Shell

euromark 11 years ago
parent
commit
98c191c7ff

+ 250 - 0
src/Shell/InflectShell.php

@@ -0,0 +1,250 @@
+<?php
+namespace Tools\Shell;
+
+use Cake\Console\Shell;
+use Cake\Utility\Inflector;
+use Cake\Core\Plugin;
+
+/**
+ * Inflect Shell
+ *
+ * Inflect the heck out of your word(s)
+ *
+ * @author Jose Diaz-Gonzalez
+ * @author Mark Scherer
+ * @license http://www.opensource.org/licenses/mit-license.php The MIT License
+ */
+class InflectShell extends Shell {
+
+	/**
+	 * Valid inflection rules
+	 *
+	 * @var string
+	 */
+	public $validMethods = array(
+		'pluralize', 'singularize', 'camelize',
+		'underscore', 'humanize', 'tableize',
+		'classify', 'variable', 'dasherize', 'slug'
+	);
+
+	/**
+	 * Valid inflection rules
+	 *
+	 * @var string
+	 */
+	public $validCommands = array(
+		'pluralize', 'singularize', 'camelize',
+		'underscore', 'humanize', 'tableize',
+		'classify', 'variable', 'dasherize', 'slug', 'all', 'quit'
+	);
+
+	/**
+	 * Inflects words
+	 *
+	 * @return void
+	 */
+	public function main() {
+		if (!empty($this->args)) {
+			$arguments = $this->_parseArguments($this->args);
+		} else {
+			$arguments = $this->_interactive();
+		}
+		$this->_inflect($arguments['method'], $arguments['words']);
+	}
+
+	/**
+	 * Prompts the user for words
+	 *
+	 * @return array
+	 * @author Jose Diaz-Gonzalez
+	 */
+	protected function _interactive() {
+		$method = $this->_getMethod();
+		$words = $this->_getWords();
+		return array('method' => $method, 'words' => $words);
+	}
+
+	/**
+	 * Requests a valid inflection method
+	 *
+	 * @return void
+	 * @author Jose Diaz-Gonzalez
+	 */
+	protected function _getMethod() {
+		$validCharacters = array('1', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'q');
+		$validCommands = array_merge($validCharacters, $this->validCommands);
+
+		$command = null;
+		while (empty($command)) {
+			$this->out("Please type the number or name of the inflection method you would like to use");
+			$this->hr();
+			$this->out("[1] Pluralize");
+			$this->out("[2] Singularize");
+			$this->out("[3] Camelize");
+			$this->out("[4] Underscore");
+			$this->out("[5] Humanize");
+			$this->out("[6] Tableize");
+			$this->out("[7] Classify");
+			$this->out("[8] Variable");
+			$this->out("[9] Dasherize");
+			$this->out("[10] Slug");
+			$this->out("[q] Quit");
+			$temp = $this->in("What command would you like to perform?", null, 'q');
+			if (in_array(strtolower($temp), $validCommands)) {
+				$command = strtolower($temp);
+			} else {
+				$this->out("Try again.");
+			}
+		}
+
+		switch ($command) {
+			case '1' :
+			case 'pluralize' :
+				return 'pluralize';
+				break;
+			case '2' :
+			case 'singularize' :
+				return 'singularize';
+				break;
+			case '3' :
+			case 'camelize' :
+				return 'camelize';
+				break;
+			case '4' :
+			case 'underscore' :
+				return 'underscore';
+				break;
+			case '5' :
+			case 'humanize' :
+				return 'humanize';
+				break;
+			case '6' :
+			case 'tableize' :
+				return 'tableize';
+				break;
+			case '7' :
+			case 'classify' :
+				return 'classify';
+				break;
+			case '8' :
+			case 'variable' :
+				return 'variable';
+			case '9' :
+			case 'dasherize' :
+				return 'dasherize';
+			case '10' :
+			case 'slug' :
+				return 'slug';
+			case 'q' :
+			case 'quit' :
+			default :
+				$this->out(__("Exit"));
+				return $this->_stop();
+		}
+	}
+
+	/**
+	 * Requests words to inflect
+	 *
+	 * @return array
+	 * @author Jose Diaz-Gonzalez
+	 */
+	protected function _getWords() {
+		$words = null;
+		while (empty($words)) {
+			$temp = $this->in("What word(s) would you like to inflect?");
+			if (!empty($temp)) {
+				$words = $temp;
+			} else {
+				$this->out("Try again.");
+			}
+		}
+		return $words;
+	}
+
+	/**
+	 * Parse the arguments into the function and the word(s) to be inflected
+	 *
+	 * @return array
+	 * @author Jose Diaz-Gonzalez
+	 */
+	protected function _parseArguments($arguments) {
+		$words = null;
+		$function = $arguments[0];
+		unset($arguments[0]);
+		if (!in_array($function, array_merge($this->validMethods, array('all')))) {
+			$function = $this->_getMethod();
+		}
+
+		$arguments = array_reverse($arguments);
+		if (count($arguments) == 0) {
+			$words = $this->_getWords();
+		} else {
+			while (count($arguments) > 0) {
+				$words .= array_pop($arguments);
+				if (count($arguments) > 0) {
+					$words .= " ";
+				}
+			}
+		}
+
+		return array('method' => $function, 'words' => $words);
+	}
+
+	/**
+	 * Inflects a set of words based upon the inflection set in the arguments
+	 *
+	 * @return void
+	 */
+	protected function _inflect($function, $words) {
+		$this->out($words);
+		if ($function === 'all') {
+			foreach ($this->validMethods as $method) {
+				$functionName = $this->_getMessage($method);
+				$this->out("{$functionName}: " . Inflector::$method($words));
+			}
+		} else {
+			$functionName = $this->_getMessage($function);
+			$this->out("{$functionName}: " . Inflector::$function($words));
+		}
+	}
+
+	/**
+	 * Returns the appropriate message for a given function
+	 *
+	 * @return void
+	 */
+	protected function _getMessage($function) {
+		$messages = array(
+			'camelize' => 'CamelCase form             ',
+			'classify' => 'Cake Model Class form      ',
+			'humanize' => 'Human Readable Group form  ',
+			'singularize' =>	'Singular form              ',
+			'dasherize' => 'Dasherized-form               ',
+			'slug' => 'Slugged-form               ',
+			'pluralize' => 'Pluralized form            ',
+			'tableize' => 'table_names form           ',
+			'underscore' => 'under_scored_form          ',
+			'variable' => 'variableForm               '
+		);
+		return $messages[$function];
+	}
+
+	/**
+	 * Displays help contents
+	 *
+	 * @return void
+	 */
+	public function help() {
+		$this->out('Inflector Shell');
+		$this->out('');
+		$this->out('This shell uses the Inflector class to inflect any word(s) you wish');
+		$this->hr();
+		$this->out("Usage: cake inflect");
+		$this->out("       cake inflect methodName");
+		$this->out("       cake inflect methodName word");
+		$this->out("       cake inflect methodName words to inflect");
+		$this->out('');
+	}
+
+}

+ 0 - 198
src/Shell/WhitespaceShell.php

@@ -1,198 +0,0 @@
-<?php
-namespace Tools\Shell;
-
-use Cake\Console\Shell;
-use Cake\Filesystem\Folder;
-use Cake\Utility\Inflector;
-use Cake\Core\Plugin;
-
-/**
- * Shell to remove superfluous whitespace.
- *
- * @author Mark Scherer
- * @license MIT
- */
-class WhitespaceShell extends Shell {
-
-	/**
-	 * Each report: [0] => found, [1] => corrected
-	 *
-	 * @var array
-	 */
-	public $report = array(
-		'leading' => array(0, 0),
-		'trailing' => array(0, 0)
-	);
-
-	/**
-	 * Whitespaces before or after <?php and ?>.
-	 * The latter should be removed from PHP files by the way.
-	 *
-	 * @return void
-	 */
-	public function clean() {
-		if (!empty($this->args[0])) {
-			$folder = realpath($this->args[0]);
-		} elseif ($this->params['plugin']) {
-			$folder = Plugin::path(Inflector::classify($this->params['plugin']));
-		} else {
-			$folder = APP;
-		}
-		$App = new Folder($folder);
-		$this->out("Checking *.php in " . $folder);
-
-		$files = $App->findRecursive('.*\.php');
-		$this->out('Found ' . count($files) . ' files.');
-
-		$action = $this->in('Continue? [y]/[n]', array('y', 'n'), 'n');
-		if ($action !== 'y') {
-			return $this->error('Aborted');
-		}
-
-		$folders = array();
-
-		foreach ($files as $file) {
-			$errors = array();
-			$action = '';
-			$this->out('Processing ' . $file, 1, Shell::VERBOSE);
-
-			$c = file_get_contents($file);
-			if (preg_match('/^[\n\r|\n|\r|\s]+\<\?php/', $c)) {
-				$errors[] = 'leading';
-			}
-			if (preg_match('/\?\>[\n\r|\n|\r|\s]+$/', $c)) {
-				$errors[] = 'trailing';
-			}
-
-			if (empty($errors)) {
-				continue;
-			}
-			foreach ($errors as $e) {
-				$this->report[$e][0]++;
-			}
-			$this->out('');
-			$this->out('contains ' . implode(' and ' , $errors) . ' whitespaces: ' . $this->shortPath($file));
-
-			$dirname = dirname($file);
-			if (in_array($dirname, $folders)) {
-				$action = 'y';
-			}
-
-			while (empty($action)) {
-				$action = $this->in('Remove? [y]/[n], [a] for all in this folder, [r] for all below, [*] for all files(!), [q] to quit', array('y', 'n', 'r', 'a', 'q', '*'), 'q');
-			}
-
-			if ($action === '*') {
-				$action = 'y';
-
-			} elseif ($action === 'a') {
-				$action = 'y';
-				$folders[] = $dirname;
-				$this->out('All: ' . $dirname);
-			}
-
-			if ($action === 'q') {
-				return $this->error('Abort... Done');
-			}
-
-			if ($action === 'y') {
-				if (in_array('leading', $errors)) {
-					$c = preg_replace('/^\s+\<\?php/', '<?php', $c);
-				}
-				if (in_array('trailing', $errors)) {
-					$c = preg_replace('/\?\>\s+$/', '?>', $c);
-				}
-
-				file_put_contents($file, $c);
-				foreach ($errors as $e) {
-					$this->report[$e][1]++;
-				}
-				$this->out('fixed ' . implode(' and ' , $errors) . ' whitespaces: ' . $this->shortPath($file));
-			}
-		}
-
-		// Report.
-		$this->out('--------');
-		$this->out('found ' . $this->report['leading'][0] . ' leading, ' . $this->report['trailing'][0] . ' trailing ws');
-		$this->out('fixed ' . $this->report['leading'][1] . ' leading, ' . $this->report['trailing'][1] . ' trailing ws');
-	}
-
-	/**
-	 * Whitespaces at the end of the file
-	 *
-	 * @return void
-	 */
-	public function eof() {
-		if (!empty($this->args[0])) {
-			$folder = realpath($this->args[0]);
-		} else {
-			$folder = APP;
-		}
-		$App = new Folder($folder);
-		$this->out("Checking *.php in " . $folder);
-
-		$files = $App->findRecursive('.*\.php');
-
-		$this->out('Found ' . count($files) . ' files.');
-
-		$action = $this->in('Continue? [y]/[n]', array('y', 'n'), 'n');
-		if ($action !== 'y') {
-			return $this->error('Aborted');
-		}
-
-		foreach ($files as $file) {
-			$this->out('Processing ' . $file, 1, Shell::VERBOSE);
-			$content = $store = file_get_contents($file);
-
-			$newline = PHP_EOL;
-			$x = substr_count($content, "\r\n");
-			if ($x > 0) {
-				$newline = "\r\n";
-			} else {
-				$newline = "\n";
-			}
-
-			// add one new line at the end
-			$content = trim($content) . $newline;
-			if ($content !== $store) {
-				file_put_contents($file, $content);
-			}
-		}
-		$this->out('Done');
-	}
-
-	public function getOptionParser() {
-		$subcommandParser = array(
-			'options' => array(
-				'ext' => array(
-					'short' => 'e',
-					'help' => 'Specify extensions [php|txt|...]',
-					'default' => '',
-				),
-				'dry-run' => array(
-					'short' => 'd',
-					'help' => 'Dry run the clear command, no files will actually be deleted. Should be combined with verbose!',
-					'boolean' => true
-				),
-				'plugin' => array(
-					'short' => 'p',
-					'help' => 'Plugin',
-					'default' => '',
-				),
-			)
-		);
-
-		return parent::getOptionParser()
-			->description('The Whitespace Shell removes uncessary/wrong whitespaces.
-Either provide a path as first argument, use -p PluginName or run it as it is for the complete APP dir.')
-			->addSubcommand('clean', array(
-				'help' => 'Detect and remove any leading/trailing whitespaces',
-				'parser' => $subcommandParser
-			))
-			->addSubcommand('eof', array(
-				'help' => 'Fix whitespace issues at the end of PHP files (a single newline as per coding standards)',
-				'parser' => $subcommandParser
-			));
-	}
-
-}

+ 92 - 0
tests/TestCase/Shell/InflectShellTest.php

@@ -0,0 +1,92 @@
+<?php
+namespace Tools\Test\TestCase\Shell;
+
+use Tools\Shell\InflectShell;
+use Cake\Console\ConsoleIo;
+use Cake\Console\ConsoleOutput;
+use Cake\Console\Shell;
+use Cake\Core\Plugin;
+use Cake\TestSuite\TestCase;
+
+/**
+ * Class TestCompletionStringOutput
+ *
+ */
+class TestInflectOutput extends ConsoleOutput {
+
+	public $output = '';
+
+	protected function _write($message) {
+		$this->output .= $message;
+	}
+
+}
+
+/**
+ */
+class InflectShellTest extends TestCase {
+
+	/**
+	 * setUp method
+	 *
+	 * @return void
+	 */
+	public function setUp() {
+		parent::setUp();
+
+		$this->out = new TestInflectOutput();
+		$io = new ConsoleIo($this->out);
+
+		$this->Shell = $this->getMock(
+			'Tools\Shell\InflectShell',
+			['in', 'err', '_stop'],
+			[$io]
+		);
+	}
+
+	/**
+	 * tearDown
+	 *
+	 * @return void
+	 */
+	public function tearDown() {
+		parent::tearDown();
+		unset($this->Shell);
+	}
+
+	/**
+	 * test that the startup method supresses the shell header
+	 *
+	 * @return void
+	 */
+	public function testMain() {
+		$this->Shell->expects($this->any())->method('in')
+			->will($this->returnValue('FooBar'));
+
+		$this->Shell->runCommand(['pluralize']);
+		$output = $this->out->output;
+		$expected = 'FooBars';
+		$this->assertContains($expected, $output);
+
+		$this->Shell->runCommand(['underscore']);
+		$output = $this->out->output;
+		$expected = 'foo_bar';
+		$this->assertContains($expected, $output);
+
+		$this->Shell->runCommand(['dasherize']);
+		$output = $this->out->output;
+		$expected = 'foo-bar';
+		$this->assertContains($expected, $output);
+
+		$this->Shell->runCommand(['slug']);
+		$output = $this->out->output;
+		$expected = 'foo-bar';
+		$this->assertContains($expected, $output);
+
+		$this->Shell->runCommand(['tableize']);
+		$output = $this->out->output;
+		$expected = 'foo_bar';
+		$this->assertContains($expected, $output);
+	}
+
+}

+ 0 - 82
tests/TestCase/Shell/WhitespaceShellTest.php

@@ -1,82 +0,0 @@
-<?php
-namespace Tools\Test\TestCase\Shell;
-
-use Tools\Shell\WhitespaceShell;
-use Cake\Console\ConsoleIo;
-use Cake\Console\ConsoleOutput;
-use Cake\Console\Shell;
-use Cake\Core\Plugin;
-use Cake\TestSuite\TestCase;
-
-/**
- * Class TestCompletionStringOutput
- *
- */
-class TestWhitespaceOutput extends ConsoleOutput {
-
-	public $output = '';
-
-	protected function _write($message) {
-		$this->output .= $message;
-	}
-
-}
-
-/**
- */
-class WhitespaceShellTest extends TestCase {
-
-/**
- * setUp method
- *
- * @return void
- */
-	public function setUp() {
-		parent::setUp();
-
-		$this->out = new TestWhitespaceOutput();
-		$io = new ConsoleIo($this->out);
-
-		$this->Shell = $this->getMock(
-			'Tools\Shell\WhitespaceShell',
-			['in', 'err', '_stop'],
-			[$io]
-		);
-	}
-
-/**
- * tearDown
- *
- * @return void
- */
-	public function tearDown() {
-		parent::tearDown();
-		unset($this->Shell);
-	}
-
-/**
- * test that the startup method supresses the shell header
- *
- * @return void
- */
-	public function testClean() {
-		$this->Shell->expects($this->any())->method('in')
-			->will($this->returnValue('y'));
-
-		$content = PHP_EOL . ' <?php echo $foo;' . PHP_EOL . '?> ' . PHP_EOL . PHP_EOL;
-		file_put_contents(TMP . 'Foo.php', $content);
-		$this->Shell->runCommand(['clean', TMP]);
-		$output = $this->out->output;
-
-		$this->assertTextContains('Found 1 files.', $output);
-		$this->assertTextContains('found 1 leading, 1 trailing ws', $output);
-		$this->assertTextContains('fixed 1 leading, 1 trailing ws', $output);
-
-		$output = file_get_contents(TMP . 'Foo.php');
-		$expected = '<?php echo $foo;' . PHP_EOL . '?>';
-
-		unlink(TMP . 'Foo.php');
-		$this->assertEquals($expected, $output);
-	}
-
-}