diff --git a/.gitignore b/.gitignore index e43b0f9..9ab76a1 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ .DS_Store +*.pyc +__pycache__ diff --git a/README.md b/README.md index f6cea1d..d4ea3ac 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ ![Screenshot](https://user-images.githubusercontent.com/604167/42200962-8c4c8a76-7e4a-11e8-9642-cffbef06798f.png) -An [Alfred 4](https://www.alfredapp.com/) workflow for generating [lorem ipsum](https://en.wikipedia.org/wiki/Lorem_ipsum) dummy text using [joshtronic/php-loremipsum](https://github.com/joshtronic/php-loremipsum). +An [Alfred 4](https://www.alfredapp.com/) workflow for generating [lorem ipsum](https://en.wikipedia.org/wiki/Lorem_ipsum) dummy text using [JarryShaw/lorem](https://github.com/JarryShaw/lorem). ## Installation diff --git a/info.plist b/info.plist index 03f2fbc..8c92359 100644 --- a/info.plist +++ b/info.plist @@ -131,7 +131,7 @@ escaping 127 script - php -f script.php "characters" "{query}" + python3 lipsum.py characters {query} scriptargtype 0 scriptfile @@ -153,6 +153,8 @@ clipboardtext {query} + ignoredynamicplaceholders + transient @@ -161,7 +163,7 @@ uid 125F91DD-9720-45BD-9F14-08966CFC2643 version - 2 + 3 config @@ -213,7 +215,7 @@ escaping 127 script - php -f script.php "words" "{query}" + python3 lipsum.py words {query} scriptargtype 0 scriptfile @@ -228,6 +230,27 @@ version 2 + + config + + argumenttype + 1 + keyword + lipsum + subtext + Generate {query} sentences + text + Sentences + withspace + + + type + alfred.workflow.input.keyword + uid + 1029C7B6-DB95-4448-B3C5-C33F3DA0F894 + version + 1 + config @@ -236,7 +259,7 @@ escaping 127 script - php -f script.php "sentences" "{query}" + python3 lipsum.py sentences {query} scriptargtype 0 scriptfile @@ -251,27 +274,6 @@ version 2 - - config - - argumenttype - 1 - keyword - lipsum - subtext - Generate {query} sentences - text - Sentences - withspace - - - type - alfred.workflow.input.keyword - uid - 1029C7B6-DB95-4448-B3C5-C33F3DA0F894 - version - 1 - config @@ -301,7 +303,7 @@ escaping 127 script - php -f script.php "paragraphs" "{query}" + python3 lipsum.py paragraphs {query} scriptargtype 0 scriptfile @@ -318,7 +320,7 @@ readme - An Alfred 3 workflow for generating lorem ipsum dummy text using joshtronic/php-loremipsum. + An Alfred 4 workflow for generating lorem ipsum dummy text. uidata 1029C7B6-DB95-4448-B3C5-C33F3DA0F894 @@ -385,8 +387,10 @@ 10 + variablesdontexport + version - 2.2.0 + 3.0.0 webaddress https://github.com/alexchantastic/alfred-lipsum-workflow diff --git a/lib/LoremIpsum.php b/lib/LoremIpsum.php deleted file mode 100644 index 69e4de6..0000000 --- a/lib/LoremIpsum.php +++ /dev/null @@ -1,372 +0,0 @@ - - * @copyright Copyright 2014, 2015, 2016, 2017, 2018 Josh Sherman - * @license http://www.opensource.org/licenses/mit-license.html - * @link https://github.com/joshtronic/php-loremipsum - */ - -namespace joshtronic; - -class LoremIpsum -{ - /** - * First - * - * Whether or not we should be starting the string with "Lorem ipsum..." - * - * @access private - * @var boolean - */ - private $first = false; - - /** - * Words - * - * A lorem ipsum vocabulary of sorts. Not a complete list as I'm unsure if - * a complete list exists and if so, where to get it. - * - * @access private - * @var array - */ - public $words = array( - // Lorem ipsum... - 'lorem', 'ipsum', 'dolor', 'sit', 'amet', 'consectetur', 'adipiscing', 'elit', - - // and the rest of the vocabulary - 'a', 'ac', 'accumsan', 'ad', 'aenean', 'aliquam', 'aliquet', 'ante', - 'aptent', 'arcu', 'at', 'auctor', 'augue', 'bibendum', 'blandit', - 'class', 'commodo', 'condimentum', 'congue', 'consequat', 'conubia', - 'convallis', 'cras', 'cubilia', 'curabitur', 'curae', 'cursus', - 'dapibus', 'diam', 'dictum', 'dictumst', 'dignissim', 'dis', 'donec', - 'dui', 'duis', 'efficitur', 'egestas', 'eget', 'eleifend', 'elementum', - 'enim', 'erat', 'eros', 'est', 'et', 'etiam', 'eu', 'euismod', 'ex', - 'facilisi', 'facilisis', 'fames', 'faucibus', 'felis', 'fermentum', - 'feugiat', 'finibus', 'fringilla', 'fusce', 'gravida', 'habitant', - 'habitasse', 'hac', 'hendrerit', 'himenaeos', 'iaculis', 'id', - 'imperdiet', 'in', 'inceptos', 'integer', 'interdum', 'justo', - 'lacinia', 'lacus', 'laoreet', 'lectus', 'leo', 'libero', 'ligula', - 'litora', 'lobortis', 'luctus', 'maecenas', 'magna', 'magnis', - 'malesuada', 'massa', 'mattis', 'mauris', 'maximus', 'metus', 'mi', - 'molestie', 'mollis', 'montes', 'morbi', 'mus', 'nam', 'nascetur', - 'natoque', 'nec', 'neque', 'netus', 'nibh', 'nisi', 'nisl', 'non', - 'nostra', 'nulla', 'nullam', 'nunc', 'odio', 'orci', 'ornare', - 'parturient', 'pellentesque', 'penatibus', 'per', 'pharetra', - 'phasellus', 'placerat', 'platea', 'porta', 'porttitor', 'posuere', - 'potenti', 'praesent', 'pretium', 'primis', 'proin', 'pulvinar', - 'purus', 'quam', 'quis', 'quisque', 'rhoncus', 'ridiculus', 'risus', - 'rutrum', 'sagittis', 'sapien', 'scelerisque', 'sed', 'sem', 'semper', - 'senectus', 'sociosqu', 'sodales', 'sollicitudin', 'suscipit', - 'suspendisse', 'taciti', 'tellus', 'tempor', 'tempus', 'tincidunt', - 'torquent', 'tortor', 'tristique', 'turpis', 'ullamcorper', 'ultrices', - 'ultricies', 'urna', 'ut', 'varius', 'vehicula', 'vel', 'velit', - 'venenatis', 'vestibulum', 'vitae', 'vivamus', 'viverra', 'volutpat', - 'vulputate', - ); - - /** - * Word - * - * Generates a single word of lorem ipsum. - * - * @access public - * @param mixed $tags string or array of HTML tags to wrap output with - * @return string generated lorem ipsum word - */ - public function word($tags = false) - { - return $this->words(1, $tags); - } - - /** - * Words Array - * - * Generates an array of lorem ipsum words. - * - * @access public - * @param integer $count how many words to generate - * @param mixed $tags string or array of HTML tags to wrap output with - * @return array generated lorem ipsum words - */ - public function wordsArray($count = 1, $tags = false) - { - return $this->words($count, $tags, true); - } - - /** - * Words - * - * Generates words of lorem ipsum. - * - * @access public - * @param integer $count how many words to generate - * @param mixed $tags string or array of HTML tags to wrap output with - * @param boolean $array whether an array or a string should be returned - * @return mixed string or array of generated lorem ipsum words - */ - public function words($count = 1, $tags = false, $array = false) - { - $words = array(); - $word_count = 0; - - // Shuffles and appends the word list to compensate for count - // arguments that exceed the size of our vocabulary list - while ($word_count < $count) { - $shuffle = true; - - while ($shuffle) { - $this->shuffle(); - - // Checks that the last word of the list and the first word of - // the list that's about to be appended are not the same - if (!$word_count || $words[$word_count - 1] != $this->words[0]) { - $words = array_merge($words, $this->words); - $word_count = count($words); - $shuffle = false; - } - } - } - - $words = array_slice($words, 0, $count); - - return $this->output($words, $tags, $array); - } - - /** - * Sentence - * - * Generates a full sentence of lorem ipsum. - * - * @access public - * @param mixed $tags string or array of HTML tags to wrap output with - * @return string generated lorem ipsum sentence - */ - public function sentence($tags = false) - { - return $this->sentences(1, $tags); - } - - /** - * Sentences Array - * - * Generates an array of lorem ipsum sentences. - * - * @access public - * @param integer $count how many sentences to generate - * @param mixed $tags string or array of HTML tags to wrap output with - * @return array generated lorem ipsum sentences - */ - public function sentencesArray($count = 1, $tags = false) - { - return $this->sentences($count, $tags, true); - } - - /** - * Sentences - * - * Generates sentences of lorem ipsum. - * - * @access public - * @param integer $count how many sentences to generate - * @param mixed $tags string or array of HTML tags to wrap output with - * @param boolean $array whether an array or a string should be returned - * @return mixed string or array of generated lorem ipsum sentences - */ - public function sentences($count = 1, $tags = false, $array = false) - { - $sentences = array(); - - for ($i = 0; $i < $count; $i++) { - $sentences[] = $this->wordsArray($this->gauss(24.46, 5.08)); - } - - $this->punctuate($sentences); - - return $this->output($sentences, $tags, $array); - } - - /** - * Paragraph - * - * Generates a full paragraph of lorem ipsum. - * - * @access public - * @param mixed $tags string or array of HTML tags to wrap output with - * @return string generated lorem ipsum paragraph - */ - public function paragraph($tags = false) - { - return $this->paragraphs(1, $tags); - } - - /** - * Paragraph Array - * - * Generates an array of lorem ipsum paragraphs. - * - * @access public - * @param integer $count how many paragraphs to generate - * @param mixed $tags string or array of HTML tags to wrap output with - * @return array generated lorem ipsum paragraphs - */ - public function paragraphsArray($count = 1, $tags = false) - { - return $this->paragraphs($count, $tags, true); - } - - /** - * Paragraphss - * - * Generates paragraphs of lorem ipsum. - * - * @access public - * @param integer $count how many paragraphs to generate - * @param mixed $tags string or array of HTML tags to wrap output with - * @param boolean $array whether an array or a string should be returned - * @return mixed string or array of generated lorem ipsum paragraphs - */ - public function paragraphs($count = 1, $tags = false, $array = false) - { - $paragraphs = array(); - - for ($i = 0; $i < $count; $i++) { - $paragraphs[] = $this->sentences($this->gauss(5.8, 1.93)); - } - - return $this->output($paragraphs, $tags, $array, "\n\n"); - } - - /** - * Gaussian Distribution - * - * This is some smart kid stuff. I went ahead and combined the N(0,1) logic - * with the N(m,s) logic into this single function. Used to calculate the - * number of words in a sentence, the number of sentences in a paragraph - * and the distribution of commas in a sentence. - * - * @access private - * @param double $mean average value - * @param double $std_dev stadnard deviation - * @return double calculated distribution - */ - private function gauss($mean, $std_dev) - { - $x = mt_rand() / mt_getrandmax(); - $y = mt_rand() / mt_getrandmax(); - $z = sqrt(-2 * log($x)) * cos(2 * pi() * $y); - - return $z * $std_dev + $mean; - } - - /** - * Shuffle - * - * Shuffles the words, forcing "Lorem ipsum..." at the beginning if it is - * the first time we are generating the text. - * - * @access private - */ - private function shuffle() - { - if ($this->first) { - $this->first = array_slice($this->words, 0, 8); - $this->words = array_slice($this->words, 8); - - shuffle($this->words); - - $this->words = $this->first + $this->words; - - $this->first = false; - } else { - shuffle($this->words); - } - } - - /** - * Punctuate - * - * Applies punctuation to a sentence. This includes a period at the end, - * the injection of commas as well as capitalizing the first letter of the - * first word of the sentence. - * - * @access private - * @param array $sentences the sentences we would like to punctuate - */ - private function punctuate(&$sentences) - { - foreach ($sentences as $key => $sentence) { - $words = count($sentence); - - // Only worry about commas on sentences longer than 4 words - if ($words > 4) { - $mean = log($words, 6); - $std_dev = $mean / 6; - $commas = round($this->gauss($mean, $std_dev)); - - for ($i = 1; $i <= $commas; $i++) { - $word = round($i * $words / ($commas + 1)); - - if ($word < ($words - 1) && $word > 0) { - $sentence[$word] .= ','; - } - } - } - - $sentences[$key] = ucfirst(implode(' ', $sentence) . '.'); - } - } - - /** - * Output - * - * Does the rest of the processing of the strings. This includes wrapping - * the strings in HTML tags, handling transformations with the ability of - * back referencing and determining if the passed array should be converted - * into a string or not. - * - * @access private - * @param array $strings an array of generated strings - * @param mixed $tags string or array of HTML tags to wrap output with - * @param boolean $array whether an array or a string should be returned - * @param string $delimiter the string to use when calling implode() - * @return mixed string or array of generated lorem ipsum text - */ - private function output($strings, $tags, $array, $delimiter = ' ') - { - if ($tags) { - if (!is_array($tags)) { - $tags = array($tags); - } else { - // Flips the array so we can work from the inside out - $tags = array_reverse($tags); - } - - foreach ($strings as $key => $string) { - foreach ($tags as $tag) { - // Detects / applies back reference - if ($tag[0] == '<') { - $string = str_replace('$1', $string, $tag); - } else { - $string = sprintf('<%1$s>%2$s', $tag, $string); - } - - $strings[$key] = $string; - } - } - } - - if (!$array) { - $strings = implode($delimiter, $strings); - } - - return $strings; - } -} diff --git a/lib/__init__.py b/lib/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/lib/lorem/LICENSE b/lib/lorem/LICENSE new file mode 100755 index 0000000..be383ed --- /dev/null +++ b/lib/lorem/LICENSE @@ -0,0 +1,29 @@ +BSD 3-Clause License + +Copyright (c) 2019, Jarry Shaw +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/lib/lorem/__init__.py b/lib/lorem/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/lib/lorem/lorem.py b/lib/lorem/lorem.py new file mode 100755 index 0000000..5299264 --- /dev/null +++ b/lib/lorem/lorem.py @@ -0,0 +1,436 @@ +# -*- coding: utf-8 -*- +"""lorem ipsum generator + +In publishing and graphic design, lorem ipsum is a placeholder text commonly +used to demonstrate the visual form of a document or a typeface without +relying on meaningful content. + +The :mod:`lorem` module provides a generic access to generating the lorem ipsum +text from its very original text:: + + Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod + tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim + veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea + commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit + esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat + cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id + est laborum. + +Usage of the :mod:`lorem` module is rather simple. Depending on your needs, the +:mod:`lorem` module provides generation of *words*, *sentences*, and +*paragraphs*. + +Get Random Words +---------------- + +The :mod:`lorem` module provides two different ways for getting random words. + +1. :func:`word` -- generate a list of random words + + .. code:: python + + word(count=1, func=None, args=(), kwargs={}) -> Iterator[str] + +2. :func:`get_word` -- return random words + + .. code:: python + + get_word(count=1, sep=' ', func=None, args=(), kwargs={}) -> str + +Get Random Sentences +-------------------- + +The :mod:`lorem` module provides two different ways for getting random sentences. + +1. :func:`sentence` -- generate a list of random sentences + + .. code:: python + + sentence(count=1, comma=(0, 2), word_range=(4, 8)) -> Iterator[str] + +2. :func:`get_sentence` -- return random sentences + + .. code :: python + + get_sentence(count=1, sep=' ', comma=(0, 2), word_range=(4, 8)) -> Union[str] + +Get Random Paragraphs +--------------------- + +The :mod:`lorem` module provides two different ways for getting random paragraphs. + +1. :func:`paragraph` -- generate a list of random paragraphs + + .. code:: python + + paragraph(count=1, comma=(0, 2), word_range=(4, 8), sentence_range=(5, 10)) -> Iterator[str] + +2. :func:`get_paragraph` -- return random paragraphs + + .. code:: python + + get_paragraph(count=1, sep=os.linesep, comma=(0, 2), word_range=(4, 8), sentence_range=(5, 10)) -> Union[str] + +Customise Word Pool +------------------- + +If wanted, the :mod:`lorem` module also provides an interface to customise the word +pool as you wish. + +1. :func:`set_pool` -- customise random word pool + + .. code:: python + + set_pool(pool) + +""" +import itertools +import os +import random +import typing + +__all__ = [ + 'set_pool', + 'word', 'sentence', 'paragraph', + 'get_word', 'get_sentence', 'get_paragraph', +] + +#: The original lorem ipsum text pool. +_TEXT = ('ad', 'adipiscing', 'aliqua', 'aliquip', 'amet', 'anim', 'aute', 'cillum', 'commodo', + 'consectetur', 'consequat', 'culpa', 'cupidatat', 'deserunt', 'do', 'dolor', 'dolore', + 'duis', 'ea', 'eiusmod', 'elit', 'enim', 'esse', 'est', 'et', 'eu', 'ex', 'excepteur', + 'exercitation', 'fugiat', 'id', 'in', 'incididunt', 'ipsum', 'irure', 'labore', 'laboris', + 'laborum', 'lorem', 'magna', 'minim', 'mollit', 'nisi', 'non', 'nostrud', 'nulla', + 'occaecat', 'officia', 'pariatur', 'proident', 'qui', 'quis', 'reprehenderit', 'sed', + 'sint', 'sit', 'sunt', 'tempor', 'ullamco', 'ut', 'velit', 'veniam', 'voluptate') + + +def _gen_pool(dupe: int = 1) -> typing.Iterator[str]: + """Generate word pool. + + Args: + dupe (int): Duplication to generate the word pool. + + Returns: + :obj:`Iterator[str]`: An infinite loop word pool. + + """ + pool = list() + for _ in range(dupe): + pool.extend(_TEXT) + random.shuffle(pool) + + while pool: # pragma: no cover + for text in pool: + yield text + random.shuffle(pool) + + +def _gen_word(pool: typing.Iterator[str], # pylint: disable=dangerous-default-value + func: typing.Optional[typing.Union[str, typing.Callable[[str], str]]] = None, + args: typing.Tuple[str] = (), kwargs: typing.Dict[str, str] = {}) -> str: + """Generate random word. + + Args: + pool (:obj:`Iterator[str]`): Word pool, returned by :func:`_gen_pool`. + func (:obj:`Optional[Union[str, Callable[[str], str]]]`): Filter function. It can be an + attribute name of :obj:`str`, or a customised function that takes the original :obj:`str` + and returns the modified :obj:`str`. + args (:obj:`Tuple[str]`): Additional positional arguments for ``func``. + kwargs (:obj:`Dict[str, Any]`): Additional keyword arguments for ``func``. + + Returns: + :obj:`str`: Random word. + + """ + text = next(pool) + if func is not None: + if isinstance(func, str): + text = getattr(text, func)(*args, **kwargs) + else: + text = func(text, *args, **kwargs) + return text + + +def _gen_sentence(pool: typing.Iterator[str], + comma: typing.Tuple[int], + word_range: typing.Tuple[int]) -> str: + """Generate random sentence. + + Args: + pool (:obj:`Iterator[str]`): Word pool, returned by :func:`_gen_pool`. + comma (:obj:`Tuple[int]`): Random range for number of commas. The function will use + :func:`random.randint` to choose a random integer as the number of commas. + word_range (:obj:`Tuple[int]`): Random range for number of words in each sentence. + The function will use :func:`random.randint` to choose a random integer as the + number of words. + + Returns: + :obj:`str`: Random sentence. + + """ + text = _gen_word(pool=pool, func='capitalize') + for _ in range(random.randint(*word_range) - 1): + text += ' ' + _gen_word(pool=pool) + + for _ in range(random.randint(*comma)): + include_comma = random.choice([True, False]) + if include_comma: + text += ',' + for _ in range(random.randint(*word_range)): + text += ' ' + _gen_word(pool=pool) + continue + break + return text + '.' + + +def _gen_paragraph(pool: typing.Iterator[str], + comma: typing.Tuple[int], + word_range: typing.Tuple[int], + sentence_range: typing.Tuple[int]) -> str: + """Generate random paragraph. + + Args: + pool (:obj:`Iterator[str]`): Word pool, returned by :func:`_gen_pool`. + comma (:obj:`Tuple[int]`): Random range for number of commas. The function will use + :func:`random.randint` to choose a random integer as the number of commas. + word_range (:obj:`Tuple[int]`): Random range for number of words in each sentence. + The function will use :func:`random.randint` to choose a random integer as the + number of words. + sentence_range (:obj:`Tuple[int]`): Random range for number of sentences in each + paragraph. The function will use :func:`random.randint` to choose a random integer + as the number of sentences. + + Returns: + :obj:`str`: Random paragraph. + + """ + text = _gen_sentence(pool=pool, comma=comma, word_range=word_range) + for _ in range(random.randint(*sentence_range) - 1): + text += ' ' + _gen_sentence(pool=pool, comma=comma, word_range=word_range) + return text + + +def word(count: int = 1, # pylint: disable=dangerous-default-value + func: typing.Optional[typing.Union[str, typing.Callable[[str], str]]] = None, + args: typing.Tuple[str] = (), kwargs: typing.Dict[str, str] = {}) -> typing.Iterator[str]: + """Generate a list of random words. + + .. code:: python + + >>> list(itertools.cycle(word(count=3), 3)) + ['labore', 'tempor', 'commodo'] + >>> list(itertools.cycle(word(count=3, func='capitalize'), 3)) + ['Ea', 'Lorem', 'Do'] + >>> list(itertools.cycle(word(count=3, func=lambda s: s.upper()), 3)) + ['UT', 'AMET', 'EXCEPTEUR'] + + Args: + count (int): Number of non-repeated random words. + func (:obj:`Optional[Union[str, Callable[[str], str]]]`): Filter function. + It can be an attribute name of :obj:`str`, or a customised function that + takes the original :obj:`str` and returns the modified :obj:`str`. + args (:obj:`Tuple[str]`): Additional positional arguments for ``func``. + kwargs (:obj:`Dict[str, Any]`): Additional keyword arguments for ``func``. + + Returns: + :obj:`Iterator[str]`: Indefinite random words generator. + + """ + pool = _gen_pool(count) + yield from itertools.cycle(_gen_word(pool=pool, + func=func, + args=args, + kwargs=kwargs) for _ in range(count)) + + +def sentence(count: int = 1, + comma: typing.Tuple[int] = (0, 2), + word_range: typing.Tuple[int] = (4, 8)) -> typing.Iterator[str]: + """Generate a list of random sentences. + + .. code:: python + + >>> list(itertools.islice(sentence(), 1)) + ['Aute irure et commodo sunt do duis dolor.'] + + Args: + count (int): Number of non-repeated random sentences. + comma (:obj:`Tuple[int]`): Random range for number of commas. The function will + use :func:`random.randint` to choose a random integer as the number of commas. + word_range (:obj:`Tuple[int]`): Random range for number of words in each sentence. + The function will use :func:`random.randint` to choose a random integer as the + number of words. + + Returns: + :obj:`Iterator[str]`: Indefinite random sentence generator. + + """ + pool = _gen_pool(count * random.randint(*word_range)) + yield from itertools.cycle(_gen_sentence(pool=pool, + comma=comma, + word_range=word_range) for _ in range(count)) + + +def paragraph(count: int = 1, + comma: typing.Tuple[int] = (0, 2), + word_range: typing.Tuple[int] = (4, 8), + sentence_range: typing.Tuple[int] = (5, 10)) -> typing.Iterator[str]: + """Generate a list of random paragraphs. + + .. code:: python + + >>> list(itertools.islice(paragraph(), 1)) + ['Aute sint et cupidatat aliquip. Non exercitation est aliquip voluptate ' + 'fugiat, reprehenderit ad occaecat laboris velit consequat. Magna enim ' + 'deserunt aute laborum fugiat exercitation. Aliqua ex sunt fugiat in ' + 'magna voluptate. Elit nisi exercitation nostrud. Magna proident et ' + 'fugiat eiusmod cupidatat fugiat, sit culpa fugiat non ea eu ' + 'reprehenderit elit. Proident mollit mollit ut cillum. Nostrud voluptate ' + 'aliquip cupidatat anim.'] + + Args: + count (int): Number of non-repeated random paragraphs. + comma (:obj:`Tuple[int]`): Random range for number of commas. The function + will use :func:`random.randint` to choose a random integer as the number + of commas. + word_range (:obj:`Tuple[int]`): Random range for number of words in each sentence. + The function will use :func:`random.randint` to choose a random integer as the + number of words. + sentence_range (:obj:`Tuple[int]`): Random range for number of sentences in each + paragraph. The function will use :func:`random.randint` to choose a random + integer as the number of sentences. + + Returns: + :obj:`Iterator[str]`: Random paragraph generator. + + """ + pool = _gen_pool(count * random.randint(*word_range) * random.randint(*sentence_range)) + yield from itertools.cycle(_gen_paragraph(pool=pool, + comma=comma, + word_range=word_range, + sentence_range=sentence_range) for _ in range(count)) + + +def get_word(count: typing.Union[int, typing.Tuple[int]] = 1, # pylint: disable=dangerous-default-value + sep: str = ' ', + func: typing.Optional[typing.Union[str, typing.Callable[[str], str]]] = None, + args: typing.Tuple[str] = (), kwargs: typing.Dict[str, str] = {}) -> str: + """Return random words. + + .. code:: python + + >>> get_word(count=3) + 'anim voluptate non' + >>> get_word(count=3, func='capitalize') + 'Non Labore Ut' + >>> get_word(count=3, func=lambda s: s.upper()) + 'NISI TEMPOR CILLUM' + + Args: + count (:obj:`Union[int, Tuple[int]]`): Number of random words. To generate random + number of words, supply a 2-element tuple of :obj:`int`, the function will use + :func:`random.randint` to choose a random integer as the number of random words. + sep (str): Seperator between each word. + func (:obj:`Optional[Union[str, Callable[[str], str]]]`): Filter function. It can be + a function name of :obj:`str`, or a customised function that takes the original + :obj:`str` and returns the modified :obj:`str`. + args (:obj:`Tuple[str]`): Additional positional arguments for ``func``. + kwargs (:obj:`Dict[str, Any]`): Additional keyword arguments for ``func``. + + Returns: + :obj:`str`: Random words. + + """ + if isinstance(count, tuple): + count = random.randint(*count) + return sep.join(itertools.islice(word(count, func, args, kwargs), count)) + + +def get_sentence(count: typing.Union[int, typing.Tuple[int]] = 1, + sep: str = ' ', + comma: typing.Tuple[int] = (0, 2), + word_range: typing.Tuple[int] = (4, 8)) -> str: + """Return random sentences. + + .. code:: python + + >>> get_sentence() + 'Nostrud laboris lorem minim sit culpa, aliqua nostrud in amet, sint pariatur eiusmod esse.' + + Args: + + count (:obj:`Union[int, Tuple[int]]`): Number of random sentences. To generate + random number of sentences, supply a 2-element tuple of :obj:`int`, the + function will use :func:`random.randint` to choose a random integer as the number + of random sentences. + sep (str): Seperator between each sentence. + comma (:obj:`Tuple[int]`): Random range for number of commas. The function will use + :func:`random.randint` to choose a random integer as the number of commas. + word_range (:obj:`Tuple[int]`): Random range for number of words in each sentence. + The function will use :func:`random.randint` to choose a random integer as the + number of words. + + Returns: + :obj:`str`: Random sentences. + + """ + if isinstance(count, tuple): + count = random.randint(*count) + return sep.join(itertools.islice(sentence(count, comma, word_range), count)) + + +def get_paragraph(count: typing.Union[int, typing.Tuple[int]] = 1, + sep: str = os.linesep, + comma: typing.Tuple[int] = (0, 2), + word_range: typing.Tuple[int] = (4, 8), + sentence_range: typing.Tuple[int] = (5, 10)) -> str: + """Return random paragraphs. + + .. code:: python + + >>> get_paragraph() + 'Exercitation magna sunt excepteur irure adipiscing commodo duis. Est ' + 'ipsum qui deserunt, deserunt nostrud reprehenderit esse. Do velit ' + 'est in velit sed. Sunt officia officia lorem. Commodo lorem ' + 'exercitation veniam officia pariatur velit. Deserunt deserunt sed ' + 'consequat laborum consequat dolor. Et consectetur irure sint elit tempor,' + ' est minim nisi eiusmod id excepteur. Minim cillum veniam sed aliquip ' + 'anim sit, pariatur nostrud ex cillum laboris laborum. Laborum ullamco ' + 'mollit elit. Amet id incididunt ipsum sed.' + + Args: + count (:obj:`Union[int, Tuple[int]]`): Number of random paragraphs. To generate + random number of paragraphs, supply a 2-element tuple of :obj:`int`, the function + will use :func:`random.randint` to choose a random integer as the number of random + paragraphs. + sep (str): Seperator between each paragraph. The default value is OS-dependent as + :data:`os.linsep` (``\\r\\n`` on Windows, ``\\n`` on POSIX). + comma (:obj:`Tuple[int]`): Random range for number of commas. The function will use + :func:`random.randint` to choose a random integer as the number of commas. + word_range (:obj:`Tuple[int]`): Random range for number of words in each sentence. + The function will use :func:`random.randint` to choose a random integer as the + number of words. + sentence_range (:obj:`Tuple[int]`): Random range for number of sentences in each + paragraph. The function will use :func:`random.randint` to choose a random integer + as the number of sentences. + + Returns: + :obj:`str`: Random paragraphs. + + """ + if isinstance(count, tuple): + count = random.randint(*count) + return sep.join(itertools.islice(paragraph(count, comma, word_range, sentence_range), count)) + + +def set_pool(pool: typing.Iterable[str]): + """Customise random word pool. + + Args: + + pool (:obj:`Iterable[str]`): List of words to be used as random word pool. + + """ + global _TEXT + _TEXT = pool diff --git a/lipsum.py b/lipsum.py new file mode 100644 index 0000000..056a14c --- /dev/null +++ b/lipsum.py @@ -0,0 +1,32 @@ +import sys +from lib.lorem import lorem + +args = sys.argv +type = args[1] +count = int(args[2]) if len(args) >= 3 else 1 + +def get_character(count): + pool = lorem.get_word(1) + + while len(pool) <= count: + pool += ' ' + lorem.get_word(1) + + return pool[0:count] + +def lipsum(type): + if type == 'characters': + return get_character(count).capitalize() + + elif type == 'words': + return lorem.get_word(count).capitalize() + + elif type == 'sentences': + return lorem.get_sentence(count) + + elif type == 'paragraphs': + return lorem.get_paragraph(count, '\n\n') + + else: + return lorem.get_sentence(count) + +print(lipsum(type)) diff --git a/script.php b/script.php deleted file mode 100644 index 89905bf..0000000 --- a/script.php +++ /dev/null @@ -1,66 +0,0 @@ -word(); - $word_length = strlen($word); - - if ($word !== $words_array[$words_count - 1]) { - $character_count += $word_length + count($words_array); - - array_push($words_array, $word); - - $words_count = count($words_array); - } - } - - $words = implode(' ', $words_array); - $words = substr($words, 0, $count); - - $last_character = substr($words, -1); - - if ($last_character === ' ') { - $words = substr($words, 0, -1) . substr($lipsum->word(), 0, 1); - } - - return $words; -} - -switch ($type) { - case 'characters': - $output = characters($length); - break; - case 'words': - $output = $lipsum->words($length); - break; - case 'sentences': - $output = $lipsum->sentences($length); - break; - case 'paragraphs': - $output = $lipsum->paragraphs($length); - break; -} - -echo ucfirst($output); \ No newline at end of file