y-rb 0.3.2-x64-mingw32

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/lib/y/text.rb ADDED
@@ -0,0 +1,372 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Y
4
+ # A text can be used insert and remove string fragments. It also supports
5
+ # formatting and the concept of embeds, which are supported data types that
6
+ # added as metadata.
7
+ #
8
+ # The text is the replicated counterpart to a String. It supports a subset
9
+ # of String operations, like appending, insert at position and slicing.
10
+ #
11
+ # Someone should not instantiate a text directly, but use {Y::Doc#get_text}
12
+ # instead.
13
+ #
14
+ # @example
15
+ # doc = Y::Doc.new
16
+ # text = doc.get_text("my text")
17
+ #
18
+ # text << "Hello, World!"
19
+ # puts text.to_s
20
+ class Text
21
+ # @!attribute [r] document
22
+ #
23
+ # @return [Y::Doc] The document this text belongs to
24
+ attr_accessor :document
25
+
26
+ # Create a new text instance
27
+ #
28
+ # @param [Y::Doc] doc
29
+ def initialize(doc = nil)
30
+ @document = doc || Y::Doc.new
31
+
32
+ super()
33
+ end
34
+
35
+ # Appends a string at the end of the text
36
+ #
37
+ # @return [void]
38
+ def <<(str)
39
+ ytext_push(transaction, str)
40
+ end
41
+
42
+ # Attach listener to text changes
43
+ #
44
+ # @example Listen to changes in text type
45
+ # local = Y::Doc.new
46
+ #
47
+ # text = local.get_text("my text")
48
+ # text.attach(->(delta) { pp delta }) # { insert: "Hello, World!" }
49
+ #
50
+ # local.transact do
51
+ # text << "Hello, World!"
52
+ # end
53
+ #
54
+ # @example Listen to changes in text type
55
+ # local = Y::Doc.new
56
+ #
57
+ # text = local.get_text("my text")
58
+ # text.attach(->(delta) { pp delta }) # { insert: "Hello, World!" }
59
+ #
60
+ # text << "Hello, World!"
61
+ #
62
+ # # todo: required, otherwise segfault
63
+ # local.commit
64
+ #
65
+ # @param [Proc] callback
66
+ # @param [Block] block
67
+ # @return [Integer]
68
+ def attach(callback, &block)
69
+ return ytext_observe(callback) unless callback.nil?
70
+
71
+ ytext_observe(block.to_proc) unless block.nil?
72
+ end
73
+
74
+ # Detach listener
75
+ #
76
+ # @param [Integer] subscription_id
77
+ # @return [void]
78
+ def detach(subscription_id)
79
+ ytext_unobserve(subscription_id)
80
+ end
81
+
82
+ # Checks if text is empty
83
+ #
84
+ # @example Check if text is empty
85
+ # doc = Y::Doc.new
86
+ # text = doc.get_text("my text")
87
+ #
88
+ # text.empty? # true
89
+ #
90
+ # @return [TrueClass,FalseClass]
91
+ def empty?
92
+ length.zero?
93
+ end
94
+
95
+ # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
96
+
97
+ # Insert a value at position and with optional attributes. This method is
98
+ # similar to [String#insert](https://ruby-doc.org/core-3.1.2/String.html),
99
+ # except for the optional third `attrs` argument.
100
+ #
101
+ # @example Insert a string at position
102
+ # doc = Y::Doc.new
103
+ # text = doc.get_text("my text")
104
+ # text << "Hello, "
105
+ #
106
+ # text.insert(7, "World!")
107
+ #
108
+ # puts text.to_s == "Hello, World!" # true
109
+ #
110
+ # The value can be any of the supported types:
111
+ # - Boolean
112
+ # - String
113
+ # - Numeric
114
+ # - Array (where element types must be supported)
115
+ # - Hash (where the the types of key and values must be supported)
116
+ #
117
+ # @param [Integer] index
118
+ # @param [String, Numeric, Array, Hash] value
119
+ # @param [Hash|nil] attrs
120
+ # @return [void]
121
+ def insert(index, value, attrs = nil)
122
+ if value.is_a?(String)
123
+ ytext_insert(transaction, index, value) if attrs.nil?
124
+ unless attrs.nil?
125
+ ytext_insert_with_attributes(transaction, index, value, attrs)
126
+ end
127
+ return nil
128
+ end
129
+
130
+ if can_insert?(value)
131
+ ytext_insert_embed(transaction, index, value) if attrs.nil?
132
+ unless attrs.nil?
133
+ ytext_insert_embed_with_attributes(transaction, index, value, attrs)
134
+ end
135
+ return nil
136
+ end
137
+
138
+ raise ArgumentError,
139
+ "Can't insert value. `#{value.class.name}` isn't supported."
140
+ end
141
+
142
+ # rubocop:enable Metrics/AbcSize, Metrics/MethodLength
143
+
144
+ # Applies formatting to text
145
+ #
146
+ # @example Add formatting to first word
147
+ # doc = Y::Doc.new
148
+ # text = doc.get_text("my text")
149
+ #
150
+ # attrs = {format: "bold"}
151
+ # text.format(0, 2, attrs)
152
+ #
153
+ # @param [Integer] index
154
+ # @param [Integer] length
155
+ # @param [Hash] attrs
156
+ # @return [void]
157
+ def format(index, length, attrs)
158
+ ytext_format(transaction, index, length, attrs)
159
+ end
160
+
161
+ # Returns length of text
162
+ #
163
+ # @return [Integer] Length of text
164
+ def length
165
+ ytext_length
166
+ end
167
+
168
+ alias size length
169
+
170
+ # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength
171
+
172
+ # Removes a part from text
173
+ #
174
+ # **Attention:** In comparison to String#slice, {Text#slice!} will not
175
+ # return the substring that gets removed. Even this being technically
176
+ # possible, it requires us to read the substring before removing it, which
177
+ # is not desirable in most situations.
178
+ #
179
+ # @example Removes a single character
180
+ # doc = Y::Doc.new
181
+ #
182
+ # text = doc.get_text("my text")
183
+ # text << "Hello"
184
+ #
185
+ # text.slice!(0)
186
+ #
187
+ # text.to_s == "ello" # true
188
+ #
189
+ # @example Removes a range of characters
190
+ # doc = Y::Doc.new
191
+ #
192
+ # text = doc.get_text("my text")
193
+ # text << "Hello"
194
+ #
195
+ # text.slice!(1..2)
196
+ # text.to_s == "Hlo" # true
197
+ #
198
+ # text.slice!(1...2)
199
+ # text.to_s == "Ho" # true
200
+ #
201
+ # @example Removes a range of chars from start and for given length
202
+ # doc = Y::Doc.new
203
+ #
204
+ # text = doc.get_text("my text")
205
+ # text << "Hello"
206
+ #
207
+ # text.slice!(0, 3)
208
+ #
209
+ # text.to_s == "lo" # true
210
+ #
211
+ # @overload slice!(index)
212
+ # Removes a single character at index
213
+ #
214
+ # @overload slice!(start, length)
215
+ # Removes a range of characters
216
+ #
217
+ # @overload slice!(range)
218
+ # Removes a range of characters
219
+ #
220
+ # @return [void]
221
+ def slice!(*args)
222
+ if args.size.zero?
223
+ raise ArgumentError,
224
+ "Provide one of `index`, `range`, `start, length` as arguments"
225
+ end
226
+
227
+ if args.size == 1
228
+ arg = args.first
229
+
230
+ if arg.is_a?(Range)
231
+ ytext_remove_range(transaction, arg.first, arg.last - arg.first)
232
+ return nil
233
+ end
234
+
235
+ if arg.is_a?(Numeric)
236
+ ytext_remove_range(transaction, arg.to_int, 1)
237
+ return nil
238
+ end
239
+ end
240
+
241
+ if args.size == 2
242
+ start, length = args
243
+
244
+ if start.is_a?(Numeric) && length.is_a?(Numeric)
245
+ ytext_remove_range(transaction, start, length)
246
+ return nil
247
+ end
248
+ end
249
+
250
+ raise ArgumentError, "Please check your arguments, can't slice."
251
+ end
252
+
253
+ # rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength
254
+
255
+ # Returns string representation of text
256
+ #
257
+ # @example
258
+ # doc = Y::Doc.new
259
+ # text = doc.get_text("my text")
260
+ # text << "Hello"
261
+ #
262
+ # puts text.to_s # "Hello"
263
+ #
264
+ # @return [String]
265
+ def to_s
266
+ ytext_to_s
267
+ end
268
+
269
+ private
270
+
271
+ def can_insert?(value)
272
+ value.is_a?(NilClass) ||
273
+ value.is_a?(Symbol) ||
274
+ [true, false].include?(value) ||
275
+ value.is_a?(Numeric) ||
276
+ value.is_a?(Enumerable) ||
277
+ value.is_a?(Hash)
278
+ end
279
+
280
+ # rubocop:disable Layout/LineLength
281
+
282
+ # @!method ytext_insert(transaction, index, chunk)
283
+ # Insert into text at position
284
+ #
285
+ # @param [Y::Transaction] transaction
286
+ # @param [Integer] index
287
+ # @param [String] chunk
288
+ # @return [nil]
289
+
290
+ # @!method ytext_insert_embed(transaction, index, content)
291
+ # Insert into text at position
292
+ #
293
+ # @param [Y::Transaction] transaction
294
+ # @param [Integer] index
295
+ # @param [Y::Text, Y::Array, Y::Map] content
296
+ # @return [nil]
297
+
298
+ # @!method ytext_insert_embed_with_attributes(transaction, index, embed, attrs)
299
+ # Insert into text at position
300
+ #
301
+ # @param [Y::Transaction] transaction
302
+ # @param [Integer] index
303
+ # @param [Y::Text, Y::Array, Y::Map] embed
304
+ # @param [Hash] attrs
305
+ # @return [nil]
306
+
307
+ # @!method ytext_insert_with_attributes(transaction, index, chunk, attrs)
308
+ # Insert into text at position
309
+ #
310
+ # @param [Y::Transaction] transaction
311
+ # @param [Integer] index
312
+ # @param [String] chunk
313
+ # @param [Hash] attrs
314
+ # @return [nil]
315
+
316
+ # @!method ytext_push(transaction, value)
317
+ # Returns length of text
318
+ #
319
+ # @param [Y::Transaction] transaction
320
+ # @param [String] value
321
+ # @return [nil]
322
+
323
+ # @!method ytext_remove_range(transaction, index, length)
324
+ # Removes a range from text
325
+ #
326
+ # @param [Y::Transaction] transaction
327
+ # @param [Integer] index
328
+ # @param [Integer] length
329
+ # @return [nil]
330
+
331
+ # @!method ytext_format(transaction, index, length, attrs)
332
+ # Formats a text range
333
+ #
334
+ # @param [Y::Transaction] transaction
335
+ # @param [Integer] index
336
+ # @param [Integer] length
337
+ # @param [Hash] attrs
338
+ # @return [nil]
339
+
340
+ # @!method ytext_length()
341
+ # Returns length of text
342
+ #
343
+ # @return [Integer]
344
+
345
+ # @!method ytext_observe(proc)
346
+ # Observe text changes
347
+ #
348
+ # @param [Proc] proc
349
+ # @return [Integer]
350
+
351
+ # @!method ytext_to_s()
352
+ # Returns string representation of text
353
+ #
354
+ # @return [String]
355
+
356
+ # @!method ytext_unobserve(subscription_id)
357
+ # Detach listener
358
+ #
359
+ # @param [Integer] subscription_id
360
+ # @return [void]
361
+
362
+ # rubocop:enable Layout/LineLength
363
+
364
+ # A reference to the current active transaction of the document this map
365
+ # belongs to.
366
+ #
367
+ # @return [Y::Transaction] A transaction object
368
+ def transaction
369
+ document.current_transaction
370
+ end
371
+ end
372
+ end
@@ -0,0 +1,143 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Y
4
+ class Transaction
5
+ # @!attribute [r] document
6
+ #
7
+ # @return [Y::Doc] The document this array belongs to
8
+ attr_accessor :document
9
+
10
+ def initialize(doc = nil)
11
+ @document = doc
12
+
13
+ super()
14
+ end
15
+
16
+ # Applies the binary encoded update for this document. This will bring the
17
+ # the document to the same state as the one the update is from.
18
+ #
19
+ # @param [::Array<Integer>] update
20
+ # @return [void]
21
+ def apply(update)
22
+ ytransaction_apply_update(update)
23
+ end
24
+
25
+ # Commits transaction
26
+ #
27
+ # @return [void]
28
+ def commit
29
+ ytransaction_commit
30
+ end
31
+
32
+ # Create or get array type
33
+ #
34
+ # @param [String] name
35
+ # @return [Y::Array]
36
+ def get_array(name)
37
+ array = ytransaction_get_array(name)
38
+ array.document = document
39
+ array
40
+ end
41
+
42
+ # Create or get map type
43
+ #
44
+ # @param [String] name
45
+ # @return [Y::Map]
46
+ def get_map(name)
47
+ map = ytransaction_get_map(name)
48
+ map.document = document
49
+ map
50
+ end
51
+
52
+ # Create or get text type
53
+ #
54
+ # @param [String] name
55
+ # @return [Y::Text]
56
+ def get_text(name)
57
+ text = ytransaction_get_text(name)
58
+ text.document = document
59
+ text
60
+ end
61
+
62
+ # Create or get XMLElement type
63
+ #
64
+ # @param [String] name
65
+ # @return [Y::XMLElement]
66
+ def get_xml_element(name)
67
+ xml_element = ytransaction_get_xml_element(name)
68
+ xml_element.document = document
69
+ xml_element
70
+ end
71
+
72
+ # Create or get XMLText type
73
+ #
74
+ # @param [String] name
75
+ # @return [Y::XMLText]
76
+ def get_xml_text(name)
77
+ xml_text = ytransaction_get_xml_text(name)
78
+ xml_text.document = document
79
+ xml_text
80
+ end
81
+
82
+ # Return state vector for transaction
83
+ #
84
+ # @return [::Array<Integer>]
85
+ def state
86
+ ytransaction_state_vector
87
+ end
88
+
89
+ # @!method ytransaction_apply_update(update)
90
+ # Returns or creates an array by name
91
+ #
92
+ # @param [::Array<Integer>] update
93
+ # @return [void]
94
+ # @!visibility private
95
+
96
+ # @!method ytransaction_commit()
97
+ #
98
+ # @return [void]
99
+ # @!visibility private
100
+
101
+ # @!method ytransaction_get_array(name)
102
+ # Returns or creates an array by name
103
+ #
104
+ # @param [String] name Name of the array structure to retrieve or create
105
+ # @return [Y::Array] Array structure
106
+ # @!visibility private
107
+
108
+ # @!method ytransaction_get_map(name)
109
+ # Returns or creates a map structure by name
110
+ #
111
+ # @param [String] name Name of the map structure to retrieve or create
112
+ # @return [Y::Map] Map structure
113
+ # @!visibility private
114
+
115
+ # @!method ytransaction_get_text(name)
116
+ # Returns or creates a text structure by name
117
+ #
118
+ # @param [String] name Name of the text structure to retrieve or create
119
+ # @return [Y::Text] Text structure
120
+ # @!visibility private
121
+
122
+ # @!method ytransaction_get_xml_element(name)
123
+ # Returns or creates a XML structure by name
124
+ #
125
+ # @param [String] name Name of the XML element structure to retrieve or
126
+ # create
127
+ # @return [Y::XMLElement] XMLElement structure
128
+ # @!visibility private
129
+
130
+ # @!method ytransaction_get_xml_text(name)
131
+ # Returns or creates a XML structure by name
132
+ #
133
+ # @param [String] name Name of the XML element structure to retrieve or
134
+ # create
135
+ # @return [Y::XMLElement] XMLElement structure
136
+ # @!visibility private
137
+
138
+ # @!method ytransaction_state_vector
139
+ #
140
+ # @return [Array<Integer>]
141
+ # @!visibility private
142
+ end
143
+ end
data/lib/y/version.rb ADDED
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Y
4
+ VERSION = "0.3.2"
5
+ end