ace.improved

0.2.1 • Public • Published

ace.improved

This package extends the ace editor with useful functionality such as:

  • helpers to lookup, install and remove key bindings
  • code markers
  • extended editor selection interface
  • ast based editor commands

Setup

In your webpage load ace and then include whatever parts of ace.improved you need:

<script type="text/javascript" src="http://cdn.jsdelivr.net/ace/1.2.3/noconflict/ace.js"></script> 
<script src="ace.improved/lib/ace.improvements.js"></script>
<script src="ace.improved/lib/ace.ext.keys.js"></script>
<script src="ace.improved/lib/ace.ext.lang.codemarker.js"></script>
<!--...-->

Interface

Editor object

  • editor.posToIndex(pos) => index

    Converts pos, a {column: NUMBER, line: NUMBER} object, into the string index / offset of editor.getValue().

  • editor.idxToPos(index) => pos

    The reverse of posToIndex.

  • editor.getCursorIndex() => index

    Index of the current cursor position.

  • editor.setSelection(...) => Range

    • editor.setSelection(rangeString)

      Sets the selection range via a descriptive string, such as editor.setSelection("[0/2]->[0/4]") or editor.setSelection("[0/4]->[0/2]"). The first number designates the row, the second the column.

    • editor.setSelection(startIndex, endIndex)

      Sets the selection range via a start and end index into the editor.getValue() string, example: ed.setSelection(3,10).

    • editor.setSelection(range)

      Also accepts a ace range object:

      var Range = ace.require("ace/range").Range;
      var r = new Range(1,2,3, 10);
      editor.setSelection(r)
  • editor.addSelection(...) => Range

    Like setSelection but for multiple selection ranges.

  • editor.saveExcursion(doFunction)

    Remembers the current selection state and calls doFunction with one argument, a reset function. doFunction can modify the selection state and is able to revert all selection changes by calling the reset function in turn. Example:

    editor.selectAll()
    editor.saveExcursion(function(resetFunc) {
      editor.setSelection("[0/0]->[0/10]");
      setTimeout(function() { editor.setSelection("[0/0]->[0/10]"); }, 500);
      setTimeout(function() { editor.setSelection("[1/0]->[1/10]"); }, 1000);
      setTimeout(function() { editor.setSelection("[2/0]->[2/10]"); }, 1500);
      setTimeout(resetFunc, 2000);
    });

ace.ext.keys

Some helpers around key handling: Simulating pressing keys and key sequences, looking up key bindings, easily adding and removing new key bindings.

  • ace.ext.keys.lookupKeys(editor, keyString) => Command

    Simulates inputing keyString into editor and records the editor command this invokes without running the command. Returns the command. (Editor commands are defined in editor.keyBinding.$handlers)

    Example:

    ace.ext.keys.lookupKeys(ed, "Alt-Left")
    // => {
    //   name: "gotowordleft",
    //   bindKey: {mac: "Option-Left", win: "Ctrl-Left"},
    //   exec: function(e) {/*...*/},
    //   ...
    // }

    If you want to implement an emacs-like describe-key behavior you can use ace.ext.keyscaptureEditorCommand(editor, captureCommandFunc) which is the foo behind the lookupKeys method. This little incantation lets you do that:

    var keyLib = ace.require("ace/lib/keys");
    var lastKeys = [];
    var uninstallCapture = ace.ext.keys.captureEditorCommand(editor,
      function(cmd) {
        console.log(`Pressing ${lastKeys.join(" ")}  invokes ${cmd.name}`);
        uninstallCapture();
      },
      function(hashId, keyString, keyCode, event) {
        if ((hashId in keyLib.KEY_MODS && keyCode === -1)
         || [16,17,18,91,93,224].indexOf(keyCode) > -1) return; // Just a modifier being pressed
        lastKeys.push(keyLib.KEY_MODS[hashId] + keyString);
      });
     
  • ace.ext.keys.allEditorCommands(editor) => commandMap

    Searches through all handlers and key bindings and returns a complete map of all commands in editor. Particularly, returns a JS object that maps command names to lists of command objects of the form {cmd: {/*...*/}, cmdName: "golineup", key: "up"}. For example ace.ext.keys.allEditorCommands(editor).golineup returns

    [{
      bindings: {/*...*/},
      cmdName: "golineup",
      key: "up"
    },{
      cmd: [/*...*/],
      cmdName: "golineup",
      key: "ctrl-p"
    }]
    
  • ace.ext.keys.simulateKey(editor, keyString)

    Creates a keyboard event from keyString and runs it through editor, effectively simulating user key press(es). Some normalization will be applied, e.g. 'ctrl-A' and 'Control-A' is the same. Input "H": ace.ext.keys.simulateKey(ed, 'H') Select all (Mac OS): ace.ext.keys.simulateKey(ed, 'Command-A') Select all (Win / Linux): ace.ext.keys.simulateKey(ed, 'Control-A')

  • ace.ext.keys.simulateKeys(editor, keyString)

    Splits keyString by spaces and then inputs ea part as with simulateKey. Processes both string input and command keys. Example, enters text, then select it:

    ace.ext.keys.simulateKeys(ed, 'H e l l o W o r l d Command-a');
  • ace.ext.keys.addKeyCustomizationLayer(name, layerSpec) and ace.ext.keys.removeKeyCustomizationLayer(name)

    A quick (and easily reversable) way to add key bindings to editor. For key customizations, temporary (e.g. mode dependant) key bindings etc. name is the the layer id and layerSpec is an object like

    {
      priority: NUMBER?,
      modes: [STRING]?,
      commandKeyBinding: {KEY_STRING: CMD_NAME, ...}
    }
    

    Example:

    // First: add a new command
    ed.commands.addCommands([{name: "test-command", exec: function() { alert("test-command"); }}]);
    // Now bind a key to it
    ace.ext.keys.addKeyCustomizationLayer("test-layer", {priority: 10, commandKeyBinding: {"alt-t": "test-command"}});

    When you now press alt-t you should see a popup. Separating the binding from the commands allows to easily change and override bindings:

    // Add a second command
    ed.commands.addCommands([{name: "test-command-2", exec: function() { alert("test-command-2"); }}]);
    // ... and bind it
    ace.ext.keys.addKeyCustomizationLayer("test-layer-2", {priority: 20, commandKeyBinding: {"alt-t": "test-command-2"}});

    Pressing alt-t now invokes the new command. To revert to the original behavior:

    ace.ext.keys.removeKeyCustomizationLayer("test-layer");
    ace.ext.keys.removeKeyCustomizationLayer("test-layer-2");

code markers

Easily highlight areas inside the editor.

Example, add a yellow marker to 'this' and 'test'

 
// Ensure CSS
document.head.insertAdjacentHTML(
  "beforeend",
  `<style id="codemarker-css">
    .example-codemarker {
     position: absolute;
     border-radius: 3px;
     background: rgba(204,204,0,0.7);
    }
  </style>`)
 
// set the text
ed.session.setValue("this\n is\na\n test")
 
// create a marker and highlight 'this' and 'test'
var marker = ace.ext.lang.codemarker.ensureIn(ed.session, "example-codemarker")
marker.set([{
  cssClassName: "example-codemarker",
  startPos: {row: 0, column: 0}, endPos: {row: 0, column: 4}
}, {
  cssClassName: "example-codemarker",
  startPos: {row: 3, column: 1}, endPos: {row: 3, column: 5}
}]);

ast commands

TODO add doc

attributed text mode

ed.session.setMode("ace/mode/text");
ed.session.getMode().set(ed, [
  ["Hello", {commands: [{name: 'oink', bindKey: 'enter'}]}]
]);

TODO add doc

Development

Run the tests by visiting tests/run-tests.html.

License

MIT

Package Sidebar

Install

npm i ace.improved

Weekly Downloads

140

Version

0.2.1

License

MIT

Last publish

Collaborators

  • mroeder
  • robertkrahn