<! doctype html>
<html>
  <head>
    <meta charset="utf-8">
    <title>CodeMirror: Ruby mode</title>
    <link rel="stylesheet" href="../../lib/codemirror.css">
    <script src="../../lib/codemirror.js"></script>
    <script src="../../addon/edit/matchbrackets.js"></script>
    <script src="ruby.js"></script>
    <style>
      .CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}
      .cm-s-default span.cm-arrow { color: red; }
    </style>
    <link rel="stylesheet" href="../../doc/docs.css">
  </head>
  <body>
    <h1>CodeMirror: Ruby mode</h1>
    <form><textarea id="code" name="code">
# Code from http://sandbox.mc.edu/~bennet/ruby/code/poly_rb.html
#
# This program evaluates polynomials.   It first asks for the coefficients
# of a polynomial, which must be entered on one line, highest-order first. 
# It then requests values of x and will compute the value of the poly for
# each x.  It will repeatly ask for x values, unless you the user enters
# a blank line.   It that case, it will ask for another polynomial.   If the
# user types quit for either input, the program immediately exits. 
#

#
# Function to evaluate a polynomial at x.  The polynomial is given
# as a list of coefficients, from the greatest to the least. 
def polyval(x, coef)
    sum = 0
    coef = coef.clone           # Don't want to destroy the original
    while true
        sum += coef.shift       # Add and remove the next coef
        break if coef.empty?     # If no more, done entirely. 
        sum *= x                # This happens the right number of times. 
    end
    return sum
end

#
# Function to read a line containing a list of integers and return
# them as an array of integers.   If the string conversion fails, it
# throws TypeError.   If the input line is the word 'quit', then it
# converts it to an end-of-file exception
def readints(prompt)
    # Read a line
    print prompt
    line = readline.chomp
    raise EOFError.new if line == 'quit' # You can also use a real EOF. 
            
    # Go through each item on the line, converting each one and adding it
    # to retval. 
    retval = [ ]
    for str in line.split(/\s+/)
        if str =~ /^\-?\d+$/
            retval.push(str.to_i)
        else
            raise TypeError.new
        end
    end

    return retval
end

#
# Take a coeff and an exponent and return the string representation, ignoring
# the sign of the coefficient. 
def term_to_str(coef, exp)
    ret = ""

    # Show coeff, unless it's 1 or at the right
    coef = coef.abs
    ret = coef.to_s     unless coef == 1 && exp > 0
    ret += "x" if exp > 0                               # x if exponent not 0
    ret += "^" + exp.to_s if exp > 1                    # ^exponent, if > 1. 

    return ret
end

#
# Create a string of the polynomial in sort-of-readable form. 
def polystr(p)
    # Get the exponent of first coefficient, plus 1. 
    exp = p.length

    # Assign exponents to each term, making pairs of coeff and exponent,
    # Then get rid of the zero terms. 
    p = (p.map { |c| exp -= 1; [ c, exp ] }).select { |p| p[0] ! = 0 }

    # If there's nothing left, it's a zero
    return "0" if p.empty? 

    # *** Now p is a non-empty list of [ coef, exponent ] pairs. *** 

    # Convert the first term, preceded by a "-" if it's negative. 
    result = (if p[0][0] < 0 then "-" else "" end) + term_to_str(*p[0])

    # Convert the rest of the terms, in each case adding the appropriate
    # + or - separating them.   
    for term in p[1...p.length]
        # Add the separator then the rep.  of the term. 
        result += (if term[0] < 0 then " - " else " + " end) + 
                term_to_str(*term)
    end

    return result
end
        
#
# Run until some kind of endfile. 
begin
    # Repeat until an exception or quit gets us out. 
    while true
        # Read a poly until it works.   An EOF will except out of the
        # program. 
        print "\n"
        begin
            poly = readints("Enter a polynomial coefficients: ")
        rescue TypeError
            print "Try again.\n"
            retry
        end
        break if poly.empty? 

        # Read and evaluate x values until the user types a blank line. 
        # Again, an EOF will except out of the pgm. 
        while true
            # Request an integer. 
            print "Enter x value or blank line: "
            x = readline.chomp
            break if x == ''
            raise EOFError.new if x == 'quit'

            # If it looks bad, let's try again. 
            if x ! ~ /^\-?\d+$/
                print "That doesn't look like an integer.   Please try again.\n"
                next
            end

            # Convert to an integer and print the result. 
            x = x.to_i
            print "p(x) = ", polystr(poly), "\n"
            print "p(", x, ") = ", polyval(x, poly), "\n"
        end
    end
rescue EOFError
    print "\n=== EOF ===\n"
rescue Interrupt, SignalException
    print "\n=== Interrupted ===\n"
else
    print "--- Bye ---\n"
end
</textarea></form>
    <script>
      var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
        mode: "text/x-ruby",
        tabMode: "indent",
        matchBrackets: true,
        indentUnit: 4
      });
    </script>

    <p><strong>MIME types defined:</strong> <code>text/x-ruby</code>.</p>

    <p>Development of the CodeMirror Ruby mode was kindly sponsored
    by <a href="http://ubalo.com/">Ubalo</a>, who hold
    the <a href="LICENSE">license</a>.</p>

  </body>
</html>
