all files / ui/ MacroManager.js

84% Statements 42/50
79.17% Branches 19/24
75% Functions 3/4
87.23% Lines 41/47
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      206× 206× 206×               161×       161× 161× 161×     161×   15× 15× 12× 12× 12× 12× 12× 12×   15×                     11× 11× 11× 11× 11×   11×       68× 26× 26× 26× 26× 26× 26× 26× 26× 26×     68×     67×     91×                     91×                            
class MacroManager {
 
  constructor(context, macros) {
    this.context = context
    this.macros = macros
    this.context.editorSession.onFinalize('document', this.onDocumentChanged, this)
  }
 
  dispose() {
    this.context.editorSession.off(this)
  }
 
  onDocumentChanged(change, info) {
    this.executeMacros(change, info)
  }
 
  executeMacros(change, info) {
    let doc = this.context.editorSession.getDocument()
    let nodeId, node, text, start, end
    let path
    // HACK: we exploit the information of the internal structure
    // of this document changes
    switch(info.action) {
      case 'type': {
        let op = change.ops[0]
        if (op.type === 'update' && op.diff._isTextOperation) {
          path = op.path
          nodeId = path[0]
          node = doc.get(nodeId)
          text = doc.get(path)
          start = op.diff.pos
          end = start+op.diff.getLength()
        }
        break
      }
      case 'break': {
        // FIXME: this impl turned out to be fragile,
        // as the selection before the transaction
        // can show to nodes not being there anymore
 
        // We interpret a 'break' as kind of confirmation
        // of the current node
        // so we take the original selection
        // to determine the original node
        let sel = change.before.selection
        Iif (!sel.isPropertySelection()) return
        path = sel.path
        nodeId = path[0]
        node = doc.get(nodeId)
        // HACK: fragile - before.selection is not a good reference
        if (!node || !node.isText()) return
        text = node.getText()
        start = sel.start.offset
        end = start
        break
      }
      case 'paste': {
        // HACK: just support primitive plain-text paste
        if (change.ops.length === 1) {
          let op = change.ops[0]
          Eif (op.type === 'update' && op.propertyType === 'string') {
            path = op.path
            nodeId = path[0]
            node = doc.get(nodeId)
            Iif (!node.isText()) return
            text = node.getText()
            start = op.diff.pos
            end = start+op.diff.getLength()
          }
        }
        break
      }
      default:
        return
    }
 
    let props = {
      action: info.action,
      node: node,
      path: path,
      text: text,
      start: start,
      end: end,
      editorSession: this.context.editorSession,
      selection: this.context.editorSession.getSelection()
    }
 
    setTimeout(() => {
      for (let i = 0; i < this.macros.length; i++) {
        let macro = this.macros[i]
        let executed = macro.execute(props, this.context)
        if (executed) {
          break
        }
      }
    })
 
  }
}
 
export default MacroManager