ot.rb

Build Status

This is a Ruby port of the https://github.com/Operational-Transformation/ot.js Operational Transformation library.

At this time, only TextOperation has been ported.

Installation

Add this line to your application's Gemfile:

gem 'ot'

And then execute:

$ bundle

Or install it yourself as:

$ gem install ot

Usage

TextOperation

retain(n)

Skip over a given number of charaters

insert(string)

Insert a string at the current position

delete(n)

Delete a string at the current position

noop?

Tests whether this operation has no effect.

to_a

Converts operation into an array value. Note that this replaces the toJSON method in ot.js

self.from_a(ops)

Converts an array into an operation and validates it. Note that this replaces the fromJSON method in ot.js

apply(str)

Apply an operation to a string, returning a new string. Throws an error if there's a mismatch between the input string and the operation.

invert(str)

Computes the inverse of an operation. The inverse of an operation is the operation that reverts the effects of the operation, e.g. when you have an operation 'insert("hello "); skip(6);' then the inverse is 'delete("hello "); skip(6);'. The inverse should be used for implementing undo.

compose(operation2)

Compose merges two consecutive operations into one operation, that preserves the changes of both. Or, in other words, for each input string S and a pair of consecutive operations A and B, apply(apply(S, A), B) = apply(S, compose(A, B)) must hold.

compose_with?(other)

When you use ctrl-z to undo your latest changes, you expect the program not to undo every single keystroke but to undo your last sentence you wrote at a stretch or the deletion you did by holding the backspace key down. This This can be implemented by composing operations on the undo stack. This method can help decide whether two operations should be composed. It returns true if the operations are consecutive insert operations or both operations delete text at the same position. You may want to include other factors like the time since the last change in your decision.

compose_with_inverted?(other)

Decides whether two operations should be composed with each other if they were inverted, that is shouldBeComposedWith(a, b) = shouldBeComposedWithInverted(b^{-1}, a^{-1}).

transform(operation1, operation2)

Transform takes two operations A and B that happened concurrently and produces two operations A' and B' (in an array) such that apply(apply(S, A), B') = apply(apply(S, B), A'). This function is the heart of OT.

Development

After checking out the repo, run bundle install to install dependencies. Then, run rake rspec to run the tests. You can also run bin/console for an interactive prompt that will allow you to experiment.

Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/ball-hayden/ot.rb.

License

The gem is available as open source under the terms of the MIT License.