Welcome, guest | Sign In | My Account | Store | Cart

With this macro, you can make a text/word selection, then press one of ", ', (, [ or { and the matching set of quotes/braces will be added around the selection.

Example (where | denotes the selection): This is |myselectedword|. then pressing "{" you'll get: This is {myselectedword}.

JavaScript, 104 lines
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
/**
 * @fileoverview  With an editor selection, pressing any of [ { ( " ' keys will
 *                place matching braces or quotes around the selected text.
 * @author        Todd Whiteman (toddw@activestate.com)
 * @version       0.5
 */

if (typeof(window.extensions) == 'undefined') {
    window.extensions = {};
}

if (extensions.smartbraces && extensions.smartbraces.onkeypress_handler) {
    // Remove the existing trigger handler, we'll re-instate it.
    var editor_pane = ko.views.manager.topView;
    editor_pane.removeEventListener('keypress', extensions.smartbraces.onkeypress_handler, true);
}
extensions.smartbraces = {};

(function() {

    var log = ko.logging.getLogger("SmartBraces");
    //log.setLevel(ko.logging.LOG_DEBUG);

    // The accepted keypress characters.
    var brace_charcodes =          ["{", "(", "[", "\"", "'"];
    var matching_brace_charcodes = ["}", ")", "]", "\"", "'"];

    this.onkeypress_handler = function(e) {
        try {
            // Only trap the required brace keys.
            var key = String.fromCharCode(e.charCode);
            var idx = brace_charcodes.indexOf(key);
            if (idx < 0) {
                log.debug("onkeypress_handler:: not one of the handled keys: " + key);
                return; // These are not the keys you are looking for.
            }

            // Only trap keypresses that aren't used with a modifier and
            // originated in the editor.
            if (!e.charCode || e.ctrlKey || e.altKey) return;
            if (e.getPreventDefault()) {
                // Somebody else already tried to cancel this event.
                log.debug("onkeypress_handler:: key already handled: " + key);
                return;
            }
            // Create shorthands for 'currentView'
            var view = ko.views.manager.currentView;
            var wanted_event = e.originalTarget.localName == "scintilla" ||
                                  e.originalTarget == view.scintilla._embed ||
                                  // Allow the Scintilla IME input as well.
                                  (e.originalTarget.localName == "input" &&
                                   (e.originalTarget.parentNode.parentNode ==
                                    view.scintilla.inputField));
            if (!wanted_event) {
                // The event belongs to something else.
                log.debug("onkeypress_handler:: event originated elsewhere: " + e.originalTarget.localName);
                return;
            }
            if (view.scintilla.key_handler) {
                // There is a specialized key handler registered, don't do
                // anything, as Komodo's likely in interactive search mode.
                log.debug("onkeypress_handler:: special key handler already installed");
                return;
            }

            log.debug("onkeypress_handler:: key: " + key);

            /**
             * @type {Components.interfaces.ISciMoz}
             */
            var editor = view.scimoz;

            // Don't do anything if there isn't a selection within the document.
            var selection = editor.selText;
            if (!selection) {
                return;
            }

            var anchor = editor.anchor;
            var cursorPos = editor.currentPos;
            editor.replaceSel(key + selection + matching_brace_charcodes[idx]);

            // Restore the selection.
            if (anchor < cursorPos) {
                editor.anchor = anchor;
                editor.currentPos = cursorPos + 2;
            } else {
                editor.anchor = anchor + 2;
                editor.currentPos = cursorPos;
            }

            // Stop the event from going to the editor as a regular keypress.
            e.preventDefault();
            e.stopPropagation();
        } catch(ex) {
            log.exception(ex);
        }
    }

    // Hook up the keypress event listener.
    var editor_pane = ko.views.manager.topView;
    editor_pane.addEventListener('keypress', this.onkeypress_handler, true);

}).apply(extensions.smartbraces);

4 comments

Kai Risku 12 years, 7 months ago  # | flag

Nice one, although it breaks incremental searching for any of the special characters!

Todd Whiteman (author) 12 years, 6 months ago  # | flag

Thanks - I've updated it to ignore keypresses that occur in another widget (like the incremental search).

Peter Weil 12 years, 6 months ago  # | flag

Hmm. Making a selection and pressing one of the activation keys deletes my selection and replaces it with the pair of braces, parentheses, etc. What might be causing this?

Todd Whiteman (author) 12 years, 6 months ago  # | flag

@Peter That would indicate that the macro hasn't been executed yet, or there was an error registering the macro - after installing, did you double-click the macro to enable it (or set it to trigger on Komodo startup), else anything in Komodo's "Help > Troublshooting > View log file"?