#!/usr/bin/env python
"""
 piglatin

 Translate a phrase into Pig Latin.
 (Version 1: anal)

 Usage :
   (from the command line,
    assuming this 'piglatin' file
    is on your shell's search path.)

    $ piglatin What is your name?
    Atwhay isway ouryay amenay?

 Discussion :

    This program is a response to the assignment
    "write a program that translates text into piglatin."
    It illustrates several notions about coding :

    1. The problem itself wasn't well defined.
       Many choices need to be pinned down, including
        * What specific rules of piglatin?
        * What input/ouput mechanism?
       For this code, I browsed several online piglatin
       definitions including wikipedia's, and choose
       something mostly consistent with those. And I've
       chosen a command-line input/output interface,
       using python's argparse package. 

    2. Edge cases need special attention.
       Even after dealing somewhat with capitalization,
       numbers, and puncuation, others such as
       hyphenation have not been addressed here.
    
       Third this code has bugs. For example, try
         $ piglatin 3 from 2 is -1
       or
         $ piglatin two spaces   period-colon.:
       and you'll see that
         (1) -1 is treated as a command line argument
         (2) extra whitespace is quietly dropped
         (3) colons are not handled gracefully
       One lesson to be learned is that using quotation marks
       around the phrase rather than builtin command line parsing
       would have been much cleaner.

    3. Testing at the level of functional chunks
       is worthwhile for two reasons: it lets you know
       that the inputs and outputs are what you think
       they are, and it gives a practical demo of your API.

    4.  Both documentation (i.e. APIs and overviews)
        and comments (i.e. implementation notes) are important
        parts of code. You don't want to repeat what the
        code already says, but you do want to annotate in
        a way that will help you a month from now.

    5.  The argparse package requires a fairly recent
        version on python, so this won't even run
        on many even slightly older systems, e.g.
        cs.marlboro.edu in Aug 2012 with ubuntu 10
        and python 2.6.

    Of course, sometimes all you want is a quick kludge
    (see for example piglatin2.py in this folder)
    not a speced detailed tested anal-rententive tome.
    But be aware of the tradeoffs, eh?

 Jim Mahoney | mahoney@marlboro.edu | Aug 2012 | GPL
"""

import argparse     # requires python 2.7 or higher
import doctest
import string
import re

def get_commandline_words():
    """ Return list of words given in command line,
        or False if there aren't any.
        Side effect: print help if no args or "-h".
    """
    parser = argparse.ArgumentParser(
        prog = 'piglatin',
        formatter_class = argparse.RawDescriptionHelpFormatter,
        description = """
 Convert a phrase from English to PigLatin, e.g.
    $ piglatin "This is  the phrase."
    Isthay isway ethay asephray.
 For the details, see the source code. """)
    parser.add_argument('words', nargs='*')
    ## debug command line parsing
    # print "args = '%s' " % args
    # print "phrase = '%s'" % ' '.join(args.words)
    args = parser.parse_args()
    if len(args.words) == 0:
        parser.print_help()
        return False
    else:
        return args.words

def is_number(str):
    """ Return True if a string represents a number. """
    # from stackoverflow.com/questions/354038/
    #      how-do-i-check-if-a-string-is-a-number-in-python
    # Note that 'inf' and '2e3' are python numbers return True
    try:
        float(str)
        return True
    except ValueError:
        return False

def wordpunc2pig(wordpunc):
    """ Translate a word and optional trailing punctuation to piglatin. """
    match = re.match('^(.*)([,.!?]+)$', wordpunc)
    if match:
        return word2pig(match.group(1)) + match.group(2)
    else:
        return word2pig(wordpunc)

def word2pig(word):
    """ Translate a word from English to Piglatin.
        The following tests give the rules implemented.
        >>> word2pig('straight')  # consonant start : tail + head + 'ay'
        'aightstray'
        >>> word2pig('our')       # vowel start : word + 'way'
        'ourway'
        >>> word2pig('x1')        # no vowel : word + 'ay'
        'x1ay'
        >>> word2pig('128.8')     # numbers : no change
        '128.8'
        >>> word2pig('This')      # keep capitalization
        'Isthay'
        >>> word2pig('your')      # leading y is consonant
        'ouryay'
        >>> word2pig('Try')       # interior y is vowel
        'Ytray'
        >>> word2pig('OneTwo')    # interior caps unchanged
        'OneTwoway'
        >>> word2pig('  ')        # pure whitespace unmodified
        '  '
    """
    if is_number(word) or len(word) == 0 or \
          all(char in string.whitespace for char in word):
        return word
    capitalize = word[0].isupper()
    word = word[0].lower() + word[1:]
    # word.lower() is similar but changes interior letters too.
    if word[0] in "aeiou":
        pigword = word + "way"
    else:
        match = re.compile('^([^aeiou][^aeiouy]*)([aeiouy].*)$').match(word)
        #                    (consonants)        (vowel & following)
        #                    group 1             group 2
        if match:
            pigword = match.group(2) + match.group(1) + "ay"
        else:  # consonant start but no following vowel found
            pigword = word + "ay"
    if capitalize:
        return pigword[0].upper() + pigword[1:]
        # pigword.title() would do almost the right thing here,
        # but may also change interior characters,
        # e.g. 'oneTwo'.title() is 'Onetwo' instead of 'OneTwo'.
    else:
        return pigword

if __name__ == "__main__":
    doctest.testmod()
    words = get_commandline_words()
    if words:
        print ' '.join(map(wordpunc2pig, words))

syntax highlighted by Code2HTML, v. 0.93pm6