<commit_before>var SocialCalc = require('socialcalc')
  , SpreadsheetColumn = require('spreadsheet-column')
  , column = new SpreadsheetColumn

const operationsList = [Set, InsertRow, DeleteRow, InsertCol, DeleteCol]
const operationsHash = operationsList.reduce(function(obj, op) {obj[(new op).type] = op; return obj},{})
const scInstance = new SocialCalc.SpreadsheetControl()

exports.create = function() {
  SocialCalc.ResetSheet(scInstance.sheet)
  var newScSnapshot = SocialCalc.CreateSheetSave(scInstance.sheet)
  return newScSnapshot
}

exports.apply = function(scSnapshot, ops) {
  // load snapshot into our global SocialCalc instance
  scInstance.sheet.ParseSheetSave(scSnapshot)

  // Turn ops into a command string
  var cmds = unpackOps(ops)
  .map((op) => op.serialize())
  .filter((op) => !!op)
  .forEach((cmd) => {
    var error = SocialCalc.ExecuteSheetCommand(scInstance.sheet, new SocialCalc.Parse(cmd), /*saveundo:*/false)
    if(error) throw new Error(error)
  })

  var newScSnapshot = SocialCalc.CreateSheetSave(scInstance.sheet)

  return newScSnapshot
}

exports.transform = function(ops1, ops2, side) {
  return unpackOps(ops1).map(function(op1) {
    unpackOps(ops2).forEach(function(op2) {
      op1.transformAgainst(op2, ('left'==side))
    })
    return op1
  })
}

exports.compose = function(ops1, ops2) {
  return ops1.concat(ops2)
}

exports.deserializeEdit = function(cmds) {
  return cmds.split('\n')
  .reduce((ops, cmd) => {
    var op 
    operationsList.some((Operation) => op = Operation.parse(cmd))
    if(op) op.forEach(op => ops.push(op)) // If nothing recognizes this, we filter it out.
    return ops
  }, [])
}

exports.serializeEdit = function(ops) {
  return unpackOps(ops).map((op) => op.serialize()).join('\n')
}
<commit_msg>Implement transformCursor<commit_after>var SocialCalc = require('socialcalc')
  , SpreadsheetColumn = require('spreadsheet-column')
  , column = new SpreadsheetColumn

const operationsList = [Set, InsertRow, DeleteRow, InsertCol, DeleteCol]
const operationsHash = operationsList.reduce(function(obj, op) {obj[(new op).type] = op; return obj},{})
const scInstance = new SocialCalc.SpreadsheetControl()

exports.create = function() {
  SocialCalc.ResetSheet(scInstance.sheet)
  var newScSnapshot = SocialCalc.CreateSheetSave(scInstance.sheet)
  return newScSnapshot
}

exports.apply = function(scSnapshot, ops) {
  // load snapshot into our global SocialCalc instance
  scInstance.sheet.ParseSheetSave(scSnapshot)

  // Turn ops into a command string
  var cmds = unpackOps(ops)
  .map((op) => op.serialize())
  .filter((op) => !!op)
  .forEach((cmd) => {
    var error = SocialCalc.ExecuteSheetCommand(scInstance.sheet, new SocialCalc.Parse(cmd), /*saveundo:*/false)
    if(error) throw new Error(error)
  })

  var newScSnapshot = SocialCalc.CreateSheetSave(scInstance.sheet)

  return newScSnapshot
}

exports.transform = function(ops1, ops2, side) {
  return unpackOps(ops1).map(function(op1) {
    unpackOps(ops2).forEach(function(op2) {
      op1.transformAgainst(op2, ('left'==side))
    })
    return op1
  })
}

exports.transformCursor(cursor, ops/*, isOwnOp*/) { // isOwnOp is not supported for now, its purpose eludes me
  var cursorOp = new Set(cursor, null, null)
  unpackOps(ops).forEach((op) => cursorOp = cursorOp.transformAgainst(op))
  return cursorOp.target
}

exports.compose = function(ops1, ops2) {
  return ops1.concat(ops2)
}

exports.deserializeEdit = function(cmds) {
  return cmds.split('\n')
  .reduce((ops, cmd) => {
    var op 
    operationsList.some((Operation) => op = Operation.parse(cmd))
    if(op) op.forEach(op => ops.push(op)) // If nothing recognizes this, we filter it out.
    return ops
  }, [])
}

exports.serializeEdit = function(ops) {
  return unpackOps(ops).map((op) => op.serialize()).join('\n')
}

{'fraction_non_alphanumeric': 0.1406127258444619, 'fraction_numerical': 0.0068080649384655665, 'mean_word_length': 4.592972181551977, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 18, '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': '2901668', 'n_tokens_mistral': 1252, 'n_tokens_neox': 1233, 'n_words': 267}