### Copyrights 2011, the repl.it project. Licensed under the MIT license ### # Shorthand for jQuery. $ = jQuery # The states in which the console can be. STATE_INPUT = 0 STATE_OUTPUT = 1 STATE_PROMPT = 2 # Key code values. KEY_ENTER = 13 KEY_TAB = 9 KEY_DELETE = 46 KEY_BACKSPACE = 8 KEY_LEFT = 37 KEY_RIGHT = 39 KEY_UP = 38 KEY_DOWN = 40 KEY_HOME = 36 KEY_END = 35 KEY_PAGE_UP = 33 KEY_PAGE_DOWN = 34 # CSS classes CLASS_PREFIX = 'jqconsole-' CLASS_CURSOR = "#{CLASS_PREFIX}cursor" CLASS_HEADER = "#{CLASS_PREFIX}header" CLASS_PROMPT = "#{CLASS_PREFIX}prompt" CLASS_OLD_PROMPT = "#{CLASS_PREFIX}old-prompt" CLASS_INPUT = "#{CLASS_PREFIX}input" CLASS_BLURRED = "#{CLASS_PREFIX}blurred" # Frequently used string literals E_KEYPRESS = 'keypress' EMPTY_SPAN = '' EMPTY_DIV = '
' EMPTY_SELECTOR = ':empty' NEWLINE = '\n' # Default prompt text for main and continuation prompts. DEFAULT_PROMPT_LABEL = '>>> ' DEFAULT_PROMPT_CONINUE_LABEL = '... ' # The default number of spaces inserted when indenting. DEFAULT_INDENT_WIDTH = 2 CLASS_ANSI = "#{CLASS_PREFIX}ansi-" ESCAPE_CHAR = '\x1B' ESCAPE_SYNTAX = /\[(\d*)(?:;(\d*))*m/ class Ansi COLORS: ['black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'white'] constructor: -> @klasses = []; _append: (klass) => klass = "#{CLASS_ANSI}#{klass}" if @klasses.indexOf(klass) is -1 @klasses.push klass _remove: (klasses...) => for klass in klasses if klass in ['fonts', 'color', 'background-color'] @klasses = (cls for cls in @klasses when cls.indexOf(klass) isnt CLASS_ANSI.length) else klass = "#{CLASS_ANSI}#{klass}" @klasses = (cls for cls in @klasses when cls isnt klass) _color: (i) => @COLORS[i] _style: (code) => code = 0 if code == '' code = parseInt code return if isNaN code switch code when 0 then @klasses = [] when 1 then @_append 'bold' when 2 then @_append 'lighter' when 3 then @_append 'italic' when 4 then @_append 'underline' when 5 then @_append 'blink' when 6 then @_append 'blink-rapid' when 8 then @_append 'hidden' when 9 then @_append 'line-through' when 10 then @_remove 'fonts' when 11,12,13,14,15,16,17,18,19 @_remove 'fonts' @_append "fonts-#{code - 10}" when 20 then @_append 'fraktur' when 21 then @_remove 'bold', 'lighter' when 22 then @_remove 'bold', 'lighter' when 23 then @_remove 'italic', 'fraktur' when 24 then @_remove 'underline' when 25 then @_remove 'blink', 'blink-rapid' when 28 then @_remove 'hidden' when 29 then @_remove 'line-through' when 30,31,32,33,34,35,36,37 @_remove 'color' @_append 'color-' + @_color code - 30 when 39 then @_remove 'color' when 40,41,42,43,44,45,46,47 @_remove 'background-color' @_append 'background-color-' + @_color code - 40 when 49 then @_remove 'background-color' when 51 then @_append 'framed' when 53 then @_append 'overline' when 54 then @_remove 'framed' when 55 then @_remove 'overline' getClasses: => @klasses.join ' ' _openSpan: (text) => "#{text}" _closeSpan: (text) => "#{text}" stylize: (text) => text = @_openSpan text i = 0 while (i = text.indexOf(ESCAPE_CHAR ,i)) and i isnt -1 if d = text[i...].match ESCAPE_SYNTAX @_style code for code in d[1...] text = @_closeSpan(text[0...i]) + @_openSpan text[i + 1 + d[0].length...] else i++ return @_closeSpan text # Helper functions spanHtml = (klass, content) -> "#{content or ''}" class JQConsole # Creates a console. # @arg container: The DOM element into which the console is inserted. # @arg header: Text to print at the top of the console on reset. Optional. # Defaults to an empty string. # @arg prompt_label: The label to show before the command prompt. Optional. # Defaults to DEFAULT_PROMPT_LABEL. # @arg prompt_continue: The label to show before continuation lines of the # command prompt. Optional. Defaults to DEFAULT_PROMPT_CONINUE_LABEL. constructor: (@container, header, prompt_label, prompt_continue_label) -> # Mobile devices supported sniff. @isMobile = !!navigator.userAgent.match /iPhone|iPad|iPod|Android/i @isIos = !!navigator.userAgent.match /iPhone|iPad|iPod/i @isAndroid = !!navigator.userAgent.match /Android/i @$window = $(window) # The header written when the console is reset. @header = header or '' # The prompt label used by Prompt(). @prompt_label_main = if typeof prompt_label == 'string' prompt_label else DEFAULT_PROMPT_LABEL @prompt_label_continue = (prompt_continue_label or DEFAULT_PROMPT_CONINUE_LABEL) # How many spaces are inserted when a tab character is pressed. @indent_width = DEFAULT_INDENT_WIDTH # By default, the console is in the output state. @state = STATE_OUTPUT # A queue of input/prompt operations waiting to be called. The items are # bound functions ready to be called. @input_queue = [] # The function to call when input is accepted. Valid only in # input/prompt mode. @input_callback = null # The function to call to determine whether the input should continue to the # next line. @multiline_callback = null # A table of all "recorded" inputs given so far. @history = [] # The index of the currently selected history item. If this is past the end # of @history, then the user has not selected a history item. @history_index = 0 # The command which the user was typing before browsing history. Keeping # track of this allows us to restore the user's command if they browse the # history then decide to go back to what they were typing. @history_new = '' # Whether the current input operation is using history. @history_active = false # A table of custom shortcuts, mapping character codes to callbacks. @shortcuts = {} # The main console area. Everything else happens inside this. @$console = $('
').appendTo @container
    @$console.css 
      position: 'absolute'
      top: 0
      bottom: 0
      right: 0
      left: 0
      margin: 0
      overflow: 'auto'

    # Whether the console currently has focus.
    @$console_focused = true
    
    # On screen somehow invisible textbox for input.
    # Copied from codemirror2, this works for both mobile and desktop browsers.
    @$input_container = $(EMPTY_DIV).appendTo @container
    @$input_container.css
      position: 'relative'
      width: 1
      height: 0
      overflow: 'hidden'
    @$input_source = $('