Class: Tuile::Component::TextView::Region
- Inherits:
-
Object
- Object
- Tuile::Component::TextView::Region
- Defined in:
- lib/tuile/component/text_view.rb,
sig/tuile.rbs
Overview
A logical section of a Tuile::Component::TextView's text — a contiguous run of hard lines the app wants to address as a unit (e.g. an LLM's "thinking" output vs. its assistant message). The view always has at least one region, an internal default that owns whatever hard lines aren't claimed by an app-created region.
Apps don't construct regions directly; call #create_region to get one. The handle stays valid as long as the region is attached — i.e. until #text= (or #clear) wipes the slate and installs a fresh internal default. Detached regions raise RuntimeError on every mutator and reader.
A region's position is derived from its sibling order and counts,
so growing or shrinking an earlier region implicitly shifts the
ranges of all later regions. Empty regions occupy zero rows but
still hold a position in the sequence; region.text = "" collapses
a region's visible footprint without detaching it. Pre-creating
empty placeholder regions is supported and is the natural pattern
for "I'll fill this in later" layouts.
Instance Attribute Summary collapse
-
#line_count ⇒ Integer, untyped
@return — number of hard lines this region owns.
Instance Method Summary collapse
-
#add_line(str) ⇒ void
Appends
stras a new entry in this region: starts a fresh hard line first (when the region is non-empty), then appendsstr. -
#append(str) ⇒ void
(also: #<<)
Verbatim append into this region's tail.
-
#attached? ⇒ Boolean
@return —
truewhile the region is owned by its Tuile::Component::TextView. - #check_attached ⇒ void
- #detach! ⇒ void
-
#empty? ⇒ Boolean
@return — true iff the region owns zero hard lines.
-
#initialize(view, line_count = 0) ⇒ Region
constructor
@param
view— the owning view (nevernilat construction). -
#insert(at, str) ⇒ void
Inserts
strat region-relative hard-line indexat. -
#range ⇒ ::Range[untyped]
@return — the hard-line indices this region currently occupies —
start...(start + line_count). -
#remove ⇒ void
Removes this region from its view.
-
#remove_last_n_lines(n) ⇒ void
Drops the last
nhard lines from this region's tail. -
#replace(range, str) ⇒ void
Replaces a contiguous range of this region's hard lines with the parsed content of
str. -
#text ⇒ StyledString
@return — the joined content of just this region's hard lines.
-
#text=(value) ⇒ void
Replaces all of this region's hard lines with the parsed content of
value.
Constructor Details
#initialize(view, line_count = 0) ⇒ Region
@param view — the owning view (never nil at construction).
@param line_count — number of hard lines this region owns.
916 917 918 919 |
# File 'lib/tuile/component/text_view.rb', line 916 def initialize(view, line_count = 0) @view = view @line_count = line_count end |
Instance Attribute Details
#line_count ⇒ Integer, untyped
@return — number of hard lines this region owns. Safe to read on a detached region (no error raised).
925 926 927 |
# File 'lib/tuile/component/text_view.rb', line 925 def line_count @line_count end |
Instance Method Details
#add_line(str) ⇒ void
This method returns an undefined value.
Appends str as a new entry in this region: starts a fresh
hard line first (when the region is non-empty), then appends
str. Scoped equivalent of Tuile::Component::TextView#add_line. On an empty
region behaves like #append.
@param str
1014 1015 1016 1017 1018 1019 1020 1021 1022 |
# File 'lib/tuile/component/text_view.rb', line 1014 def add_line(str) check_attached parsed = StyledString.parse(str) if empty? append(parsed) else append(StyledString.plain("\n") + parsed) end end |
#append(str) ⇒ void Also known as: <<
This method returns an undefined value.
Verbatim append into this region's tail. Same semantics as
Tuile::Component::TextView#append but scoped to the region: embedded "\n"
creates new hard lines within the region, no-leading-newline
input extends the region's last hard line. Empty / nil input
is a no-op (but still raises when detached). When the region is
the spatial tail of the view, this uses the incremental
Tuile::Component::TextView#append path; mid-document regions splice the affected
slice of the physical-row buffer (lines outside the region are
not re-wrapped).
@param str
970 971 972 973 |
# File 'lib/tuile/component/text_view.rb', line 970 def append(str) check_attached @view.send(:append_to_region, self, str) end |
#attached? ⇒ Boolean
@return — true while the region is owned by its
Tuile::Component::TextView. Becomes false permanently once detached
(typically by Tuile::Component::TextView#text= / Tuile::Component::TextView#clear).
930 931 932 |
# File 'lib/tuile/component/text_view.rb', line 930 def attached? !@view.nil? end |
#check_attached ⇒ void
This method returns an undefined value.
1085 1086 1087 |
# File 'lib/tuile/component/text_view.rb', line 1085 def check_attached raise "region is detached" unless attached? end |
#detach! ⇒ void
This method returns an undefined value.
1080 1081 1082 |
# File 'lib/tuile/component/text_view.rb', line 1080 def detach! @view = nil end |
#empty? ⇒ Boolean
@return — true iff the region owns zero hard lines. Empty regions render nothing — they still hold a position in the sequence, so subsequent mutations route to them as usual.
937 |
# File 'lib/tuile/component/text_view.rb', line 937 def empty? = @line_count.zero? |
#insert(at, str) ⇒ void
This method returns an undefined value.
Inserts str at region-relative hard-line index at.
Equivalent to replace(at...at, str). Region-scoped counterpart
of Tuile::Component::TextView#insert; at == line_count is allowed and appends
at the region's tail.
@param at — region-relative index in [0, line_count].
@param str
1051 1052 1053 |
# File 'lib/tuile/component/text_view.rb', line 1051 def insert(at, str) replace(at...at, str) end |
#range ⇒ ::Range[untyped]
@return — the hard-line indices this region currently
occupies — start...(start + line_count). Empty regions
return a degenerate exclusive range at their position (e.g.
5...5). The result is computed on each call and so always
reflects sibling mutations.
982 983 984 985 986 |
# File 'lib/tuile/component/text_view.rb', line 982 def range check_attached start = @view.send(:region_start_index, self) start...(start + @line_count) end |
#remove ⇒ void
This method returns an undefined value.
Removes this region from its view. The region's hard lines (if
any) are deleted from the buffer — subsequent regions' ranges
shift up by line_count — and the handle detaches permanently.
The view keeps its always-≥1-region invariant: if this was the
only remaining region, a fresh internal default is installed
(the app doesn't get a handle to it; call
Tuile::Component::TextView#create_region again to start tracking).
Idempotent: calling remove on an already-detached region is a
silent no-op (unlike the other mutators, which raise). This
lets cleanup paths blindly call remove without first checking
#attached?.
1001 1002 1003 1004 1005 |
# File 'lib/tuile/component/text_view.rb', line 1001 def remove return unless attached? @view.send(:remove_region, self) end |
#remove_last_n_lines(n) ⇒ void
This method returns an undefined value.
Drops the last n hard lines from this region's tail.
Subsequent regions' ranges shift up by the number actually
dropped. n is clamped to #line_count, so passing a large
n empties the region — the handle stays attached (use
#remove when the goal is to drop the region itself).
n == 0 and an already-empty region are no-ops.
@param n
1066 1067 1068 1069 1070 1071 1072 1073 |
# File 'lib/tuile/component/text_view.rb', line 1066 def remove_last_n_lines(n) check_attached raise TypeError, "expected Integer, got #{n.inspect}" unless n.is_a?(Integer) raise ArgumentError, "n must not be negative, got #{n}" if n.negative? return if n.zero? || empty? @view.send(:remove_last_n_from_region, self, n) end |
#replace(range, str) ⇒ void
This method returns an undefined value.
Replaces a contiguous range of this region's hard lines with the
parsed content of str. Region-scoped counterpart of
Tuile::Component::TextView#replace: indices are 0-based within the region
(so replace(0, "x") rewrites the region's first line, not
the buffer's). Same range conventions apply — Integer,
inclusive/exclusive Range, empty range as insertion at
begin, and begin == line_count for end-insertion.
@param range — region-relative hard-line indices.
@param str — replacement content.
1038 1039 1040 1041 |
# File 'lib/tuile/component/text_view.rb', line 1038 def replace(range, str) check_attached @view.send(:replace_in_region, self, range, str) end |
#text ⇒ StyledString
@return — the joined content of just this region's hard lines. Empty regions return StyledString::EMPTY.
942 943 944 945 |
# File 'lib/tuile/component/text_view.rb', line 942 def text check_attached @view.send(:text_for_region, self) end |
#text=(value) ⇒ void
This method returns an undefined value.
Replaces all of this region's hard lines with the parsed content
of value. Accepts the same inputs as Tuile::Component::TextView#text=; empty
or nil content collapses the region to zero hard lines.
@param value
953 954 955 956 |
# File 'lib/tuile/component/text_view.rb', line 953 def text=(value) check_attached @view.send(:set_region_text, self, value) end |