denebola 0.3.0 → 0.4.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 84880d06ec622bb6081d11f260b1e64cbfba37a9480a717208356afbfcc28108
4
- data.tar.gz: 5e7c2cba1e6fb6ecfd5f6cc49c517ff038ca09a85dc81da268e69fe74142172d
3
+ metadata.gz: 2039904dc6d7a0fcb5fed4aa2654588cc99bde0451961cf034ded4cee04c1d13
4
+ data.tar.gz: 6ea776a47897832290d5900414b7a6e663dbbc3f2310a6c513e68c236dd632d8
5
5
  SHA512:
6
- metadata.gz: 26cf63ddd365e57f19af10f195db576f21de2e7c1cf865025c6c868cfdc876f33fe8bc055366513106b68b666973eb9cd7a596bd2856273e2de23e358ff22627
7
- data.tar.gz: b26f9e6372cd7dea2413c82e29996692bca7a810f473b24cdb1fbe13e31e1702746f541b4d0a73d432880733bad5a149d6f42ea31d56c7b3ef2a2d271c4cdec4
6
+ metadata.gz: 932e37da79bfebdea36da0a517828d7d72e09378a7d704852caaef926eaa11b525d14029166bdbec3caedd1b8663199855495751e9e2ee27623c3403eed4a68e
7
+ data.tar.gz: 3677c6e1c45095b1eca7a8ecf250c55e271e0ad6379310c08ec63e352084a0da572c6ba1979f477b29d9a557edccbe46b62cdc51f8c196b2bc41ae8ac08b3ad9
data/CHANGELOG.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.4.0 — 2026-09-25
4
+
5
+ - Add a rope-backed buffer adapter for Zaniah CodeEditor.
6
+
3
7
  ## 0.3.0 — 2026-09-23
4
8
 
5
9
  - Add persistent sparse two-dimensional sheets with range summaries.
data/README.md CHANGED
@@ -133,6 +133,25 @@ rope.offset_at_utf16_point(Denebola::Point.new(0, 2)) # => 4
133
133
 
134
134
  `line(row)` omits the terminator. Rows are zero-based; empty text and a final empty row after a terminator each count as a line. A byte position between CR and LF normalizes to the following row, column zero; converting that point back returns the position after LF.
135
135
 
136
+ ### Zaniah CodeEditor buffer
137
+
138
+ The optional adapter exposes a persistent `Rope` through Zaniah's line-addressed
139
+ CodeEditor buffer interface. Denebola does not depend on Zaniah:
140
+
141
+ ```ruby
142
+ require "denebola/code_editor_buffer"
143
+ require "zaniah/ui"
144
+
145
+ buffer = Denebola::CodeEditorBuffer.new(Denebola::Rope.new("hello\nworld"))
146
+ editor = Zaniah::UI::CodeEditor.new(buffer: buffer)
147
+ ```
148
+
149
+ `line_count`, `line`, `line_start`, and `line_of` use Rope indexes; offsets are
150
+ UTF-8 byte positions. `replace`, `undo`, and `redo` keep structurally shared
151
+ snapshots, and `can_undo?`/`can_redo?` control editor actions. `to_s` materializes
152
+ the full document when CodeEditor requests its value. `LazyRope` is not accepted:
153
+ its default line count is an estimate, whereas CodeEditor needs an exact count.
154
+
136
155
  `rope.summary` exposes `bytesize`, `length`, `utf16_length`, `break_count`, `longest_row` (the earliest row with maximum width), `longest_row_length`, `first_line_length`, and `last_line_length`. `TextSummary.zero` is the identity, and `summary + other_summary` combines concatenated text, including CRLF across a boundary.
137
156
 
138
157
  ### Anchors
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../denebola"
4
+
5
+ module Denebola
6
+ # Adapts a persistent Rope to Zaniah::UI::CodeEditor's buffer interface.
7
+ # Zaniah is not required by Denebola; pass an instance as `buffer:`.
8
+ class CodeEditorBuffer
9
+ attr_reader :rope
10
+
11
+ def initialize(rope = Rope.new)
12
+ raise ArgumentError, "expected a Denebola::Rope" unless rope.is_a?(Rope)
13
+ @rope = rope
14
+ @undo = []
15
+ @redo = []
16
+ end
17
+
18
+ def line_count = @rope.line_count
19
+ def line(index) = @rope.line(index)
20
+ def line_start(index) = @rope.line_start(index)
21
+ def line_of(offset)
22
+ row = @rope.point_at(offset).row
23
+ row.positive? && @rope.line_start(row) > offset ? row - 1 : row
24
+ end
25
+ def to_s = @rope.to_s
26
+
27
+ def replace(range, text)
28
+ updated = @rope.replace(range, text)
29
+ @undo << @rope
30
+ @redo.clear
31
+ @rope = updated
32
+ self
33
+ end
34
+
35
+ def undo
36
+ return self unless can_undo?
37
+ @redo << @rope
38
+ @rope = @undo.pop
39
+ self
40
+ end
41
+
42
+ def redo
43
+ return self unless can_redo?
44
+ @undo << @rope
45
+ @rope = @redo.pop
46
+ self
47
+ end
48
+
49
+ def can_undo? = !@undo.empty?
50
+ def can_redo? = !@redo.empty?
51
+ end
52
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Denebola
4
- VERSION = "0.3.0"
4
+ VERSION = "0.4.0"
5
5
  end
data/sig/denebola.rbs CHANGED
@@ -186,6 +186,21 @@ module Denebola
186
186
  def close: () -> nil
187
187
  end
188
188
 
189
+ class CodeEditorBuffer
190
+ attr_reader rope: Rope
191
+ def initialize: (?Rope) -> void
192
+ def line_count: () -> Integer
193
+ def line: (Integer) -> String
194
+ def line_start: (Integer) -> Integer
195
+ def line_of: (Integer) -> Integer
196
+ def to_s: () -> String
197
+ def replace: (Range[Integer?], String) -> self
198
+ def undo: () -> self
199
+ def redo: () -> self
200
+ def can_undo?: () -> bool
201
+ def can_redo?: () -> bool
202
+ end
203
+
189
204
  class Anchor
190
205
  attr_reader offset: Integer
191
206
  attr_reader bias: :left | :right
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: denebola
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yudai Takada
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-09-23 00:00:00.000000000 Z
11
+ date: 2026-09-24 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Immutable text ropes plus bounded-memory, file-backed editing with line
14
14
  and UTF-16 indexing.
@@ -23,6 +23,7 @@ files:
23
23
  - README.md
24
24
  - lib/denebola.rb
25
25
  - lib/denebola/anchor.rb
26
+ - lib/denebola/code_editor_buffer.rb
26
27
  - lib/denebola/cursor.rb
27
28
  - lib/denebola/dimensions.rb
28
29
  - lib/denebola/edit.rb