<commit_before>do ($=jQuery) ->

    # Make `Ribs` globally accessible.
    root = window ? module.exports
    Ribs = root.Ribs ?= {}

    # Keyboard manager access point
    _keyboardManager = null
    Ribs.getKeyboardManager = ->
        _keyboardManager ?= new Ribs.KeyboardManager()

    class Ribs.KeyboardManager
    
        # Internal char code tree for registered hot keys.
        boundCharCodes: {}

        # A registry for all views is required when showing hotkey help pane.
        registeredViews:
            global:
                bindings: []
                tree: {}
                label: "Global"
                context: window

        options:

            # Hotkey to preceed any jump keys.
            jumpPrefixKey: "g"

            # Time allowed between hotkeys
            jumpTime: 1000

            enableKeyboardShortcuts: true

        constructor: (options) ->

            @options = _.extend @options, options

            @registerHotKey
                hotkey: "?"
                callback: @showKeyboardBindings
                context: this
                label: "Show hotkeys"

            $(window).on "keypress", @handleKeypress

        registerView: (view, label) ->
            namespace = _.uniqueId "view"
            @registeredViews[namespace] = 
                label: label
                context: view
                tree: {}
                bindings: []
            namespace

        deregisterView: (namespace) ->
            delete @registeredViews[namespace]

        # options:
        #  hotkey: string (required)
        #  label: string (required - displayed in help screen)
        #  callback: function (required)
        #  context: object (optional)
        #  namespace: string (optional)
        #  precondition: function (optional)
        registerHotKey: (options) ->
            options.charCodes ?= ( key.charCodeAt 0 for key in options.hotkey.split "" )
            ns = options.namespace ?= "global"
            root = @registeredViews[ns].tree
            for code, i in options.charCodes
                root[code] ?= { bindings: [], upcoming: 0 }
                if i is options.charCodes.length - 1
                    root[code].bindings.push options
                else
                    root[code].upcoming += 1
                root = root[code]
            @registeredViews[ns].bindings.push options
            ns

        deregisterHotKey: (options) ->
            options.charCodes ?= ( key.charCodeAt 0 for key in options.hotkey.split "" )
            ns = options.namespace ?= "global"
            root = current = @registeredViews[ns].tree
            for code, i in options.charCodes
                current = current[code]
                if i is options.charCodes.length - 1
                    current.bindings = _.reject current.bindings, (binding) ->
                        (not options.context or options.context is binding.context) and
                        (not options.callback or options.callback is binding.callback)
                else
                    current.upcoming -= 1

        registerJumpKey: (options) ->
            options.label = "Go to #{options.label}"
            options.hotkey = @options.jumpPrefixKey + options.jumpkey
            @registerHotKey options

        deregisterJumpKey: (options) ->
            options.hotkey = @options.jumpPrefixKey + options.jumpkey
            @deregisterHotKey options

        handleKeypress: (event, namespace="global") =>

            return unless @options.enableKeyboardShortcuts

            # don't do anything if user is typing text
            return if $(document.activeElement).is(":input")

            context = @currentContext ? @registeredViews[namespace].tree

            @walkContext context, event.which if context?

        walkContext: (context, charCode) ->

            clearTimeout @jumpTimeout if @jumpTimeout
            delete @currentContext
            return unless charCode of context

            context = context[charCode]

            # if there are no more possible hotkey matches, execute immediately
            if context.upcoming is 0
                @execute context
            else
                @currentContext = context
                @jumpTimeout = setTimeout =>
                    delete @currentContext
                    @execute context
                , @options.jumpTime

            false

        execute: (context) -><commit_msg>Fix to support hotkeys when the active element is input[type=radio|checkbox|button]<commit_after>do ($=jQuery) ->

    # Make `Ribs` globally accessible.
    root = window ? module.exports
    Ribs = root.Ribs ?= {}

    # Keyboard manager access point
    _keyboardManager = null
    Ribs.getKeyboardManager = ->
        _keyboardManager ?= new Ribs.KeyboardManager()

    class Ribs.KeyboardManager
    
        # Internal char code tree for registered hot keys.
        boundCharCodes: {}

        # A registry for all views is required when showing hotkey help pane.
        registeredViews:
            global:
                bindings: []
                tree: {}
                label: "Global"
                context: window

        options:

            # Hotkey to preceed any jump keys.
            jumpPrefixKey: "g"

            # Time allowed between hotkeys
            jumpTime: 1000

            enableKeyboardShortcuts: true

        constructor: (options) ->

            @options = _.extend @options, options

            @registerHotKey
                hotkey: "?"
                callback: @showKeyboardBindings
                context: this
                label: "Show hotkeys"

            $(window).on "keypress", @handleKeypress

        registerView: (view, label) ->
            namespace = _.uniqueId "view"
            @registeredViews[namespace] = 
                label: label
                context: view
                tree: {}
                bindings: []
            namespace

        deregisterView: (namespace) ->
            delete @registeredViews[namespace]

        # options:
        #  hotkey: string (required)
        #  label: string (required - displayed in help screen)
        #  callback: function (required)
        #  context: object (optional)
        #  namespace: string (optional)
        #  precondition: function (optional)
        registerHotKey: (options) ->
            options.charCodes ?= ( key.charCodeAt 0 for key in options.hotkey.split "" )
            ns = options.namespace ?= "global"
            root = @registeredViews[ns].tree
            for code, i in options.charCodes
                root[code] ?= { bindings: [], upcoming: 0 }
                if i is options.charCodes.length - 1
                    root[code].bindings.push options
                else
                    root[code].upcoming += 1
                root = root[code]
            @registeredViews[ns].bindings.push options
            ns

        deregisterHotKey: (options) ->
            options.charCodes ?= ( key.charCodeAt 0 for key in options.hotkey.split "" )
            ns = options.namespace ?= "global"
            root = current = @registeredViews[ns].tree
            for code, i in options.charCodes
                current = current[code]
                if i is options.charCodes.length - 1
                    current.bindings = _.reject current.bindings, (binding) ->
                        (not options.context or options.context is binding.context) and
                        (not options.callback or options.callback is binding.callback)
                else
                    current.upcoming -= 1

        registerJumpKey: (options) ->
            options.label = "Go to #{options.label}"
            options.hotkey = @options.jumpPrefixKey + options.jumpkey
            @registerHotKey options

        deregisterJumpKey: (options) ->
            options.hotkey = @options.jumpPrefixKey + options.jumpkey
            @deregisterHotKey options

        handleKeypress: (event, namespace="global") =>

            return unless @options.enableKeyboardShortcuts

            # don't do anything if the user is interacting with a text input field
            # (return if $el is not radio, is not checkbox, is not a button, but it is still an input element)
            return if $(document.activeElement).not(":radio").not(":checkbox").not(":button").is(":input")

            context = @currentContext ? @registeredViews[namespace].tree

            @walkContext context, event.which if context?

        walkContext: (context, charCode) ->

            clearTimeout @jumpTimeout if @jumpTimeout
            delete @currentContext
            return unless charCode of context

            context = context[charCode]

            # if there are no more possible hotkey matches, execute immediately
            if context.upcoming is 0
                @execute context
            else
                @currentContext = context
                @jumpTimeout = setTimeout =>
                    delete @currentContext
                    @execute context
                , @options.jumpTime

            false

        execute: (context) ->
{'fraction_non_alphanumeric': 0.08219775427886188, 'fraction_numerical': 0.0026163741415022347, 'mean_word_length': 1.5966600622700255, 'pattern_counts': {'":': 5, '<': 3, '<?xml version=': 0, '>': 31, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '188689', 'n_tokens_mistral': 2316, 'n_tokens_neox': 2143, 'n_words': 636}