diff options
author | Yu-Jie Lin <livibetter@gmail.com> | 2013-08-12 16:41:56 +0800 |
---|---|---|
committer | Yu-Jie Lin <livibetter@gmail.com> | 2013-08-12 16:41:56 +0800 |
commit | ed1d8e03b553dfb4ea641a5dd86b09efba5db2cd (patch) | |
tree | c4140731821409c873ab2005e0ed3fea988c2be9 | |
parent | 3ccc710d62d154cbb75782487cf533b5f4ddf3ae (diff) | |
download | smartypants-ed1d8e03b553dfb4ea641a5dd86b09efba5db2cd.tar.gz |
add CLI script
-rw-r--r-- | CHANGES.rst | 1 | ||||
-rw-r--r-- | README.rst | 56 | ||||
-rwxr-xr-x | setup.py | 21 | ||||
-rwxr-xr-x | smartypants | 30 | ||||
-rw-r--r-- | tests/test_cli.py | 64 |
5 files changed, 160 insertions, 12 deletions
diff --git a/CHANGES.rst b/CHANGES.rst index 16a5966..aa48351 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -10,6 +10,7 @@ Versions without timestamps mean they are future releases. - deprecate Pyblosxom support - add Python 3 support - add unittest and checks + - add CLI script ---- @@ -2,10 +2,13 @@ smartypants.py ============== +.. contents:: **Contents** + + Synopsis ======== -The priginal "SmartyPants" is a free web publishing plug-in for Movable Type, +The original "SmartyPants" is a free web publishing plug-in for Movable Type, Blosxom, and BBEdit that easily translates plain ASCII punctuation characters into "smart" typographic punctuation HTML entities. @@ -34,6 +37,41 @@ display text where smart quotes and other "smart punctuation" would not be appropriate, such as source code or example markup. +Installation +============ + +smartypants.py can be installed vi pip:: + + $ pip install smartypants + + +Usage +===== + +As module +--------- + +.. code:: python + + import smartypants + + text = '"SmartyPants" is smart, so is <code>smartypants.py</code> -- a Python port' + print(smartypants.smartyPants(text)) + +It outputs:: + + “SmartyPants” is smart, so is <code>smartypants.py</code> — a Python port + + +Via CLI +------- + +.. code:: sh + + $ echo '"SmartyPants" is smart, so is <code>smartypants.py</code> -- a Python port' | smartypants + “SmartyPants” is smart, so is <code>smartypants.py</code> — a Python port + + Backslash Escapes ================= @@ -92,11 +130,19 @@ Numeric values are the easiest way to configure SmartyPants' behavior: The following single-character attribute values can be combined to toggle -individual transformations from within the smarty_pants attribute. For +individual transformations from within the SmartyPants attributes. For example, to educate normal quotes and em-dashes, but not ellipses or \`\`backticks'' -style quotes: -``py['smartypants_attributes'] = "1"`` +.. code:: python + + smartypants.smartyPants(text, '1') + +In CLI: + +.. code:: sh + + echo "$text" | smartypants -a '1' "q" Educates normal quote characters: (") and ('). @@ -179,9 +225,9 @@ Algorithmic Shortcomings ------------------------ One situation in which quotes will get curled the wrong way is when -apostrophes are used at the start of leading contractions. For example: +apostrophes are used at the start of leading contractions. For example:: -``'Twas the night before Christmas.`` + 'Twas the night before Christmas. In the case above, SmartyPants will turn the apostrophe into an opening single-quote, when in fact it should be a closing one. I don't think @@ -7,10 +7,15 @@ from distutils.core import Command, setup from unittest import TestLoader, TextTestRunner import sys +CLI_script = 'smartypants' +module_name = 'smartypants' +module_file = 'smartypants.py' + +CHECK_FILES = ('.', CLI_script) + # scripts to be exculded from checking EXCLUDE_SCRIPTS = () -script_name = 'smartypants.py' # ============================================================================ @@ -76,7 +81,7 @@ class cmd_pep8(Command): print('Results') print('=======') print() - report = p8.check_files('.') + report = p8.check_files(CHECK_FILES) print() print('Statistics') @@ -132,7 +137,7 @@ class cmd_pyflakes(Command): print('Results') print('=======') print() - warnings = api.checkRecursive('.', reporter) + warnings = api.checkRecursive(CHECK_FILES, reporter) print() print('Total warnings: %d' % warnings) @@ -166,7 +171,7 @@ class cmd_pylint(Command): print() print('Exclude:', EXCLUDE_SCRIPTS) - files = ['setup.py', script_name] + glob('tests/*.py') + files = ['setup.py', CLI_script, module_file] + glob('tests/*.py') args = [ '--ignore=%s' % ','.join(EXCLUDE_SCRIPTS), '--output-format=colorized', @@ -178,7 +183,7 @@ class cmd_pylint(Command): # ============================================================================ -with open(script_name) as f: +with open(module_file) as f: meta = dict( (k.strip(' _'), eval(v)) for k, v in # There will be a '\n', with eval(), it's safe to ignore @@ -203,6 +208,7 @@ with open(script_name) as f: classifiers = [ 'Development Status :: 5 - Production/Stable', 'Intended Audience :: Developers', + 'Intended Audience :: End Users/Desktop', 'License :: OSI Approved :: BSD License', 'Operating System :: OS Independent', 'Programming Language :: Python :: 2', @@ -211,7 +217,7 @@ classifiers = [ ] setup_d = dict( - name='smartypants', + name=module_name, cmdclass={ 'pep8': cmd_pep8, 'pyflakes': cmd_pyflakes, @@ -219,7 +225,8 @@ setup_d = dict( 'test': cmd_test, }, classifiers=classifiers, - py_modules=['smartypants'], + py_modules=[module_name], + scripts=[CLI_script], **meta ) diff --git a/smartypants b/smartypants new file mode 100755 index 0000000..67adfdc --- /dev/null +++ b/smartypants @@ -0,0 +1,30 @@ +#!/usr/bin/env python +# Copyright (c) 2013 Yu-Jie Lin +# Licensed under the BSD License, for detailed license information, see COPYING + +from __future__ import print_function +import argparse +import sys + +import smartypants + + +def main(): + + parser = argparse.ArgumentParser(description='SmartyPants in Python') + parser.add_argument('-a', '--attr', + default=smartypants.default_smartypants_attr, + help='processing attributes (Default: %(default)s)') + parser.add_argument('files', metavar='FILE', type=argparse.FileType('r'), + nargs='*', help='files to be processed ') + args = parser.parse_args() + + if args.files: + for f in args.files: + print(smartypants.smartyPants(f.read(), args.attr), end='') + else: + print(smartypants.smartyPants(sys.stdin.read(), args.attr), end='') + + +if __name__ == '__main__': + main() diff --git a/tests/test_cli.py b/tests/test_cli.py new file mode 100644 index 0000000..0cf29dc --- /dev/null +++ b/tests/test_cli.py @@ -0,0 +1,64 @@ +# Copyright (c) 2013 Yu-Jie Lin +# Licensed under the BSD License, for detailed license information, see COPYING + +from __future__ import unicode_literals +import os +from subprocess import Popen, PIPE +import tempfile +import unittest + + +CLI_SCRIPT = './smartypants' + + +class TestCLI(unittest.TestCase): + + @staticmethod + def _p(args, T=None): + + if T: + T = T.encode() + + stdin = PIPE if T else None + p = Popen(args, stdin=stdin, stdout=PIPE) + output = p.communicate(input=T)[0] + + if isinstance(output, bytes): + output = output.decode() # Python 3 + + return output + + def test_pipe(self): + + T = '"foobar"' + E = '“foobar”' + + output = self._p([CLI_SCRIPT], T) + self.assertEquals(output, E) + + def test_pipe_attr(self): + + T = """"foo" ``bar''""" + + E = T + output = self._p([CLI_SCRIPT, '--attr', '0'], T) + self.assertEquals(output, E) + + E = """"foo" “bar”""" + output = self._p([CLI_SCRIPT, '--attr', 'b'], T) + self.assertEquals(output, E) + + def test_file(self): + + T = '"foobar"' + E = '“foobar”' + + F = tempfile.mkstemp()[1] + try: + with open(F, 'w') as f: + f.write(T) + + output = self._p([CLI_SCRIPT, F]) + finally: + os.remove(F) + self.assertEquals(output, E) |