Example #1
0
def enterHelpMode( terms ):
    '''
    When using rpn interactively, help is a special mode, which allows the user
    to navigate the help contents with much fewer keystrokes than having to
    invoke help over and over.
    '''
    printHelpModeHelp( )

    while True:
        try:
            line = input( 'rpn help>' )
        except EOFError:
            break

        line = line.strip( )

        if line in [ 'exit', 'quit' ]:
            break

        terms = line.split( ' ' )

        if terms[ 0 ] == 'help':
            printHelpModeHelp( )
        elif terms[ 0 ] == 'topics':
            printInteractiveHelp( )
        else:
            for term in terms:
                printHelp( operators, constants, listOperators, modifiers, term, True )
Example #2
0
def rpn( cmd_args ):
    '''
    This is the main function which processes the command-line arguments,
    handling both options and the expression to evaluate.   This function is
    mainly concerned with parsing and handling the command-line options.

    It finally calls evaluate( ) with the expression to be calculated, and
    returns the results, which can be formatted for output or used in another
    way (such as the unit test functionality).
    '''
    # initialize globals
    g.debugMode = False
    g.outputRadix = 10

    getDataPath( )

    # look for help argument before we start setting everything up (because it's faster this way)
    help = False
    helpArg = ''

    for i in range( 0, len( cmd_args ) ):
        if cmd_args[ i ] == 'help':
            help = True
        else:
            if help:
                helpArg = cmd_args[ i ]

    if help:
        parser = argparse.ArgumentParser( prog = g.PROGRAM_NAME, description = g.PROGRAM_NAME +
                                          PROGRAM_VERSION_STRING + g.PROGRAM_DESCRIPTION + '\n    ' +
                                          COPYRIGHT_MESSAGE, add_help = False,
                                          formatter_class = argparse.RawTextHelpFormatter,
                                          prefix_chars = '-' )

        parser.add_argument( 'terms', nargs = '*', metavar = 'term' )
        parser.add_argument( '-l', '--line_length', type = int, action = 'store',
                             default = g.defaultLineLength )

        args = parser.parse_args( cmd_args )

        loadUnitNameData( )

        g.operatorAliases.update( operatorAliases )

        printHelp( operators, constants, listOperators, modifiers, helpArg )
        return

    # set up the command-line options parser
    parser = argparse.ArgumentParser( prog = g.PROGRAM_NAME, description = g.PROGRAM_NAME +
                                      PROGRAM_VERSION_STRING + g.PROGRAM_DESCRIPTION + '\n    ' +
                                      COPYRIGHT_MESSAGE, add_help = False,
                                      formatter_class = argparse.RawTextHelpFormatter,
                                      prefix_chars = '-' )

    parser.add_argument( '-a', '--output_accuracy', nargs = '?', type = int, action = 'store',
                         default = g.defaultOutputAccuracy, const = g.defaultOutputAccuracy )
    parser.add_argument( '-b', '--input_radix', type = str, action = 'store',
                         default = g.defaultInputRadix )
    parser.add_argument( '-c', '--comma', action = 'store_true' )
    parser.add_argument( '-d', '--decimal_grouping', nargs = '?', type = int, action = 'store',
                         default = 0, const = g.defaultDecimalGrouping )
    parser.add_argument( '-D', '--DEBUG', action = 'store_true' )
    parser.add_argument( '-e', '--profile', action = 'store_true' )
    parser.add_argument( '-g', '--integer_grouping', nargs = '?', type = int, action = 'store',
                         default = 0, const = g.defaultIntegerGrouping )
    parser.add_argument( '-h', '--help', action = 'store_true' )
    parser.add_argument( '-i', '--identify', action = 'store_true' )
    parser.add_argument( '-l', '--line_length', type = int, action = 'store',
                         default = g.defaultLineLength )
    parser.add_argument( '-m', '--maximum_fixed', type = int, action = 'store', default = g.defaultMaximumFixed )
    parser.add_argument( '-n', '--numerals', type = str, action = 'store', default = g.defaultNumerals )
    parser.add_argument( '-o', '--octal', action = 'store_true' )
    parser.add_argument( '-p', '--precision', type = int, action = 'store', default = g.defaultPrecision )
    parser.add_argument( '-r', '--output_radix', type = str, action = 'store',
                         default = g.defaultOutputRadix )
    parser.add_argument( '-R', '--output_radix_numerals', type = int, action = 'store', default = 0 )
    parser.add_argument( '-s', '--list_format_level', nargs = '?', type = int, action = 'store', default = 0,
                         const = g.defaultListFormatLevel )
    parser.add_argument( '-t', '--timer', action = 'store_true' )
    parser.add_argument( '-T', '--time_limit', nargs = '?', type = int, action = 'store',
                         default = 0, const = g.timeLimit )
    parser.add_argument( '-v', '--verbose', action = 'store_true' )
    parser.add_argument( '-w', '--bitwise_group_size', type = int, action = 'store',
                         default = g.defaultBitwiseGroupSize )
    parser.add_argument( '-x', '--hex', action = 'store_true' )
    parser.add_argument( '-z', '--leading_zero', action = 'store_true' )
    parser.add_argument( '-!', '--print_options', action = 'store_true' )
    parser.add_argument( '-?', '--other_help', action = 'store_true' )

    # pull out the options and the terms
    options = [ ]
    terms = [ ]

    for i, arg in enumerate( cmd_args ):
        if ( len( arg ) > 1 ) and ( arg[ 0 ] == '-' ):
            if arg[ 1 ].isdigit( ):     # a negative number, not an option
                terms.append( arg )
            else:
                options.append( arg )
        else:
            terms.append( arg )

    # OK, let's parse and validate the options
    args = parser.parse_args( options )

    g.operatorAliases.update( operatorAliases )

    if args.help or args.other_help:
        loadUnitNameData( )

        printHelp( operators, constants, listOperators, modifiers, '' )
        return

    valid, errorString = validateOptions( args )

    if not valid:
        print( 'rpn:  ' + errorString )
        return

    # these are either globals or can be modified by other options (like -x)
    g.bitwiseGroupSize = args.bitwise_group_size
    g.integerGrouping = args.integer_grouping
    g.leadingZero = args.leading_zero

    # handle -a - set precision to be at least 2 greater than output accuracy
    setAccuracy( args.output_accuracy )

    # handle -b
    g.inputRadix = int( args.input_radix )

    # handle -c
    g.comma = args.comma

    # handle -d
    g.decimalGrouping = args.decimal_grouping

    # handle -D
    if args.DEBUG:
        g.debugMode = True

    # handle -i
    g.identify = args.identify

    # handle -l
    g.lineLength = args.line_length

    # handle -m
    g.maximumFixed = args.maximum_fixed

    # handle -n
    g.numerals = parseNumerals( args.numerals )

    # handle -o
    if args.octal:
        g.outputRadix = 8
        g.leadingZero = True
        g.integerGrouping = 3
        g.bitwiseGroupSize = 9

    # handle -p
    setPrecision( args.precision )

    # handle -r
    if args.output_radix == 'phi':
        g.outputRadix = g.phiBase
    elif args.output_radix == 'fib':
        g.outputRadix = g.fibBase
    elif args.output_radix == 'fac' or args.output_radix == '!':
        g.outputRadix = g.facBase
    elif args.output_radix == 'fac2' or args.output_radix == 'double_fac' or args.output_radix == '!!':
        g.outputRadix = g.doublefacBase
    elif args.output_radix == 'square' or args.output_radix == 'sqr':
        g.outputRadix = g.squareBase
    elif args.output_radix == 'lucas':
        g.outputRadix = g.lucasBase
    elif args.output_radix == 'triangular' or args.output_radix == 'tri':
        g.outputRadix = g.triangularBase
    elif args.output_radix == 'primorial':
        g.outputRadix = g.primorialBase
    elif args.output_radix == 'e':
        g.outputRadix = g.eBase
    elif args.output_radix == 'pi':
        g.outputRadix = g.piBase
    elif args.output_radix == 'sqrt2':
        g.outputRadix = g.sqrt2Base
    else:
        try:
            # if g.outputRadix was already set (e.g., by -o) then we don't want to override it
            if g.outputRadix == 10:
                g.outputRadix = int( args.output_radix )
        except ValueError:
            print( 'rpn:  can\'t interpret output radix \'%s\' as a number' % args.output_radix )
            return [ nan ]

    # handle -R
    if args.output_radix_numerals > 0:
        g.outputBaseDigits = True
        g.outputRadix = args.output_radix_numerals
    else:
        g.outputBaseDigits = False

    # -r/-R validation
    if g.outputBaseDigits:
        if ( g.outputRadix < 2 ):
            print( 'rpn:  output radix must be greater than 1' )
            return [ nan ]
    elif ( ( g.outputRadix < g.maxSpecialBase ) or ( g.outputRadix == 0 ) or
           ( g.outputRadix == 1 ) or ( g.outputRadix > 62 ) ):
        print( 'rpn:  output radix must be from 2 to 62, fib, phi, fac, doublefac, square, lucas' )
        return [ nan ]

    # handle -s
    g.listFormatLevel = args.list_format_level

    # handle -t
    g.timer = args.timer

    # handle -T
    g.timeLimit = args.time_limit

    # handle -v
    g.verbose = args.verbose

    # handle -x
    if args.hex:
        g.outputRadix = 16
        g.leadingZero = True
        g.integerGrouping = 4
        g.bitwiseGroupSize = 16

    # handle -u and -y:  mpmath wants precision of at least 53 for these functions
    if args.identify and mp.dps < 53:
        setAccuracy( 53 )

    if args.print_options:
        print( '--output_accuracy:  %d' % g.outputAccuracy )
        print( '--input_radix:  %d' % g.inputRadix )
        print( '--comma:  ' + ( 'true' if g.comma else 'false' ) )
        print( '--decimal_grouping:  %d' % g.decimalGrouping )
        print( '--integer_grouping:  %d' % g.integerGrouping )
        print( '--line_length:  %d' % g.lineLength )
        print( '--numerals:  ' + g.numerals )
        print( '--octal:  ' + ( 'true' if args.octal else 'false' ) )
        print( '--precision:  %d' % args.precision )
        print( '--output_radix:  %d' % g.outputRadix )
        print( '--output_radix_numerals:  %d' % args.output_radix_numerals )
        print( '--list_format_level:  %d' % g.listFormatLevel )
        print( '--timer:  ' + ( 'true' if args.timer else 'false' ) )
        print( '--verbose:  ' + ( 'true' if g.verbose else 'false' ) )
        print( '--bitwise_group_size:  %d' % g.bitwiseGroupSize )
        print( '--hex:  ' + ( 'true' if args.hex else 'false' ) )
        print( '--identify:  ' + ( 'true' if args.identify else 'false' ) )
        print( '--leading_zero:  ' + ( 'true' if g.leadingZero else 'false' ) )
        print( )

    g.creatingFunction = False

    # enter interactive mode if there are no arguments
    if not terms:
        if not loadUnitNameData( ):
            return

        enterInteractiveMode( )
        return

    # let's check out the arguments before we start to do any calculations
    if not validateArguments( terms ):
        return

    #newTerms = preprocessTerms( terms )
    #print( 'newTerms', newTerms )

    # waiting until we've validated the arguments to do this because it's slow
    if not loadUnitNameData( ):
        return

    if g.timer:
        g.startTime = time.process_time( )

    return evaluate( terms )