summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorgregor herrmann <gregoa@debian.org>2023-10-04 21:13:29 +0200
committergregor herrmann <gregoa@debian.org>2023-10-04 21:13:29 +0200
commit876aeebd8bc35c4975e45dc6f29fc90a8239c07c (patch)
treeef6091f4e6d38bb60fc1facca5f804f276db552f
parent54aed41557c33f455fe97e51aef2154911d5b805 (diff)
parent2db7d9222bb57beff0b3f0c44f1e0762ced3fb9f (diff)
Update upstream source from tag 'upstream/0.32'
Update to upstream version '0.32' with Debian dir 1bcd71f590ce5225eb73f1d1e30daa2f3435dce6
-rw-r--r--Build.PL2
-rw-r--r--Changes9
-rw-r--r--META.json10
-rw-r--r--META.yml10
-rw-r--r--README68
-rw-r--r--lib/Tickit/Widget/Scroller.pm121
-rw-r--r--lib/Tickit/Widget/Scroller/Item/RichText.pm19
-rw-r--r--lib/Tickit/Widget/Scroller/Item/Text.pm16
-rw-r--r--t/01item-text.t34
-rw-r--r--t/02item-richtext.t16
-rw-r--r--t/10initial.t6
11 files changed, 184 insertions, 127 deletions
diff --git a/Build.PL b/Build.PL
index 4bd5cf4..4e204e9 100644
--- a/Build.PL
+++ b/Build.PL
@@ -8,7 +8,7 @@ my $build = Module::Build->new(
module_name => 'Tickit::Widget::Scroller',
requires => {
'perl' => '5.026', # signatures
- 'Object::Pad' => '0.74', # 0.73 + bugfix
+ 'Object::Pad' => '0.800',
'String::Tagged' => 0,
'Tickit::RenderBuffer' => '0.43', # flush_to_term
diff --git a/Changes b/Changes
index 4850a1f..4e11248 100644
--- a/Changes
+++ b/Changes
@@ -1,5 +1,14 @@
Revision history for Tickit-Widget-Scroller
+0.32 2023-10-02
+ [CHANGES]
+ * Allow items to be specified by index, reverse index, or direct
+ object reference
+ * Cache pens used in RichText items for reuse; saves a lot of memory
+ in big long-running programs
+ * Updated to Object::Pad v0.800
+ * Respect non-breaking spaces when word-wrapping
+
0.31 2023-08-30
[CHANGES]
* Added `->items` accessor for querying the number of stored items
diff --git a/META.json b/META.json
index 485add6..7e21624 100644
--- a/META.json
+++ b/META.json
@@ -16,7 +16,7 @@
"prereqs" : {
"runtime" : {
"requires" : {
- "Object::Pad" : "0.74",
+ "Object::Pad" : "0.800",
"String::Tagged" : "0",
"Tickit::Pen" : "0.19",
"Tickit::RenderBuffer" : "0.43",
@@ -35,15 +35,15 @@
"provides" : {
"Tickit::Widget::Scroller" : {
"file" : "lib/Tickit/Widget/Scroller.pm",
- "version" : "0.31"
+ "version" : "0.32"
},
"Tickit::Widget::Scroller::Item::RichText" : {
"file" : "lib/Tickit/Widget/Scroller/Item/RichText.pm",
- "version" : "0.31"
+ "version" : "0.32"
},
"Tickit::Widget::Scroller::Item::Text" : {
"file" : "lib/Tickit/Widget/Scroller/Item/Text.pm",
- "version" : "0.31"
+ "version" : "0.32"
}
},
"release_status" : "stable",
@@ -53,6 +53,6 @@
],
"x_IRC" : "irc://irc.freenode.net/#tickit"
},
- "version" : "0.31",
+ "version" : "0.32",
"x_serialization_backend" : "JSON::PP version 4.07"
}
diff --git a/META.yml b/META.yml
index 09729ce..f380bf2 100644
--- a/META.yml
+++ b/META.yml
@@ -15,15 +15,15 @@ name: Tickit-Widget-Scroller
provides:
Tickit::Widget::Scroller:
file: lib/Tickit/Widget/Scroller.pm
- version: '0.31'
+ version: '0.32'
Tickit::Widget::Scroller::Item::RichText:
file: lib/Tickit/Widget/Scroller/Item/RichText.pm
- version: '0.31'
+ version: '0.32'
Tickit::Widget::Scroller::Item::Text:
file: lib/Tickit/Widget/Scroller/Item/Text.pm
- version: '0.31'
+ version: '0.32'
requires:
- Object::Pad: '0.74'
+ Object::Pad: '0.800'
String::Tagged: '0'
Tickit::Pen: '0.19'
Tickit::RenderBuffer: '0.43'
@@ -33,5 +33,5 @@ requires:
resources:
IRC: irc://irc.freenode.net/#tickit
license: http://dev.perl.org/licenses/
-version: '0.31'
+version: '0.32'
x_serialization_backend: 'CPAN::Meta::YAML version 0.018'
diff --git a/README b/README
index e959163..e6069e5 100644
--- a/README
+++ b/README
@@ -101,14 +101,14 @@ METHODS
set_on_scrolled
- $on_scrolled = $scroller->on_scrolled
+ $on_scrolled = $scroller->on_scrolled;
- $scroller->set_on_scrolled( $on_scrolled )
+ $scroller->set_on_scrolled( $on_scrolled );
Return or set the CODE reference to be called when the scroll position
is adjusted.
- $on_scrolled->( $scroller, $delta )
+ $on_scrolled->( $scroller, $delta );
This is invoked by the scroll method, including the scroll_to,
scroll_to_top and scroll_to_bottom. In normal cases it will be given
@@ -118,7 +118,7 @@ METHODS
items
- $count = scalar $scroller->items;
+ $count = $scroller->items;
Since version 0.31.
@@ -128,7 +128,7 @@ METHODS
push
- $scroller->push( @items )
+ $scroller->push( @items );
Append the given items to the end of the list.
@@ -141,7 +141,7 @@ METHODS
unshift
- $scroller->unshift( @items )
+ $scroller->unshift( @items );
Prepend the given items to the beginning of the list.
@@ -154,7 +154,7 @@ METHODS
shift
- @items = $scroller->shift( $count )
+ @items = $scroller->shift( $count );
Remove the given number of items from the start of the list and returns
them.
@@ -168,7 +168,7 @@ METHODS
pop
- @items = $scroller->pop( $count )
+ @items = $scroller->pop( $count );
Remove the given number of items from the end of the list and returns
them.
@@ -182,7 +182,7 @@ METHODS
scroll
- $scroller->scroll( $delta )
+ $scroller->scroll( $delta );
Move the display up or down by the given $delta amount; with positive
moving down. This will be a physical count of displayed lines; if some
@@ -191,36 +191,37 @@ METHODS
scroll_to
- $scroller->scroll_to( $line, $itemidx, $itemline )
+ $scroller->scroll_to( $line, $item_or_idx, $itemline );
Moves the display up or down so that display line $line contains line
- $itemline of item $itemidx. Any of these counts may be negative to
- count backwards from the display lines, items, or lines within the
- item.
+ $itemline of the item; which may be given by object reference or index
+ number. Any of these counts may be negative to count backwards from the
+ display lines, items, or lines within the item.
scroll_to_top
- $scroller->scroll_to_top( $itemidx, $itemline )
+ $scroller->scroll_to_top( $item_or_idx, $itemline );
Shortcut for scroll_to to set the top line of display; where $line is
- 0. If $itemline is undefined, it will be passed as 0. If $itemidx is
- also undefined, it will be passed as 0. Calling this method with no
+ 0. If $itemline is undefined, it will be passed as 0. If $item_or_idx
+ is also undefined, it will be passed as 0. Calling this method with no
arguments, therefore scrolls to the very top of the display.
scroll_to_bottom
- $scroller->scroll_to_bottom( $itemidx, $itemline )
+ $scroller->scroll_to_bottom( $item_or_idx, $itemline );
Shortcut for scroll_to to set the bottom line of display; where $line
- is -1. If $itemline is undefined, it will be passed as -1. If $itemidx
- is also undefined, it will be passed as -1. Calling this method with no
- arguments, therefore scrolls to the very bottom of the display.
+ is -1. If $itemline is undefined, it will be passed as -1. If
+ $item_or_idx is also undefined, it will be passed as -1. Calling this
+ method with no arguments, therefore scrolls to the very bottom of the
+ display.
line2item
- $itemidx = $scroller->line2item( $line )
+ $itemidx = $scroller->line2item( $line );
- ( $itemidx, $itemline ) = $scroller->line2item( $line )
+ ( $itemidx, $itemline ) = $scroller->line2item( $line );
Returns the item index currently on display at the given line of the
window. In list context, also returns the line number within item. If
@@ -230,14 +231,15 @@ METHODS
item2line
- $line = $scroller->item2line( $itemidx, $itemline )
+ $line = $scroller->item2line( $item_or_idx, $itemline );
- ( $line, $offscreen ) = $scroller->item2line( $itemidx, $itemline, $count_offscreen )
+ ( $line, $offscreen ) = $scroller->item2line( $item_or_idx, $itemline, $count_offscreen );
Returns the display line in the window of the given line of the item at
- the given index. $itemidx may be given negative, to count backwards
- from the last item. $itemline may be negative to count backward from
- the last line of the item.
+ the given index. $item_or_idx may be an item directly, a non-negative
+ integer to give its index, or a negative to count backwards from the
+ last item. $itemline may be negative to count backward from the last
+ line of the item.
In list context, also returns a value describing the offscreen nature
of the item. For items fully on display, this value is undef. If the
@@ -251,13 +253,13 @@ METHODS
lines_above
- $count = $scroller->lines_above
+ $count = $scroller->lines_above;
Returns the number of lines of content above the scrolled display.
lines_below
- $count = $scroller->lines_below
+ $count = $scroller->lines_below;
Returns the number of lines of content below the scrolled display.
@@ -265,9 +267,9 @@ METHODS
set_gen_bottom_indicator
- $scroller->set_gen_top_indicator( $method )
+ $scroller->set_gen_top_indicator( $method );
- $scroller->set_gen_bottom_indicator( $method )
+ $scroller->set_gen_bottom_indicator( $method );
Accessors for the generators for the top and bottom indicator text. If
set, each should be a CODE reference or method name on the scroller
@@ -277,14 +279,14 @@ METHODS
in an indicator window. This will be a small one-line window displayed
at the top right or bottom right corner of the Scroller's window.
- $text = $scroller->$method()
+ $text = $scroller->$method();
The ability to pass method names allows subclasses to easily implement
custom logic as methods without having to capture a closure.
update_indicators
- $scroller->update_indicators
+ $scroller->update_indicators;
Calls any defined generators for indicator text, and updates the
indicator windows with the returned text. This may be useful if the
diff --git a/lib/Tickit/Widget/Scroller.pm b/lib/Tickit/Widget/Scroller.pm
index b2f374c..57de1a8 100644
--- a/lib/Tickit/Widget/Scroller.pm
+++ b/lib/Tickit/Widget/Scroller.pm
@@ -5,9 +5,9 @@
use v5.26; # signatures
use warnings;
-use Object::Pad 0.73 ':experimental(adjust_params init_expr)';
+use Object::Pad 0.800 ':experimental(adjust_params)';
-package Tickit::Widget::Scroller 0.31;
+package Tickit::Widget::Scroller 0.32;
class Tickit::Widget::Scroller
:strict(params)
:isa(Tickit::Widget);
@@ -188,15 +188,31 @@ ADJUST :params (
method cols () { 1 }
method lines () { 1 }
-method _item ( $idx )
+method _itemidx_for ( $item_or_idx )
{
- return $_items[$idx];
+ if( ref $item_or_idx ) {
+ my $idx;
+ $_items[$_] == $item_or_idx and ( $idx = $_ ), last for 0 .. $#_items;
+ croak '$item_or_idx is not an item in the Scroller' if !defined $idx;
+ return $idx;
+ }
+
+ if( $item_or_idx < 0 ) {
+ $item_or_idx += @_items;
+
+ croak '$item_or_idx out of bounds' if $item_or_idx < 0;
+ }
+ else {
+ croak '$item_or_idx out of bounds' if $item_or_idx >= @_items;
+ }
+
+ return $item_or_idx;
}
method _itemheight ( $idx )
{
return $_itemheights[$idx] if defined $_itemheights[$idx];
- return $_itemheights[$idx] = $self->_item( $idx )->height_for_width( $self->window->cols );
+ return $_itemheights[$idx] = $_items[$idx]->height_for_width( $self->window->cols );
}
method reshape ()
@@ -255,14 +271,14 @@ method window_gained ( $win )
=head2 set_on_scrolled
- $on_scrolled = $scroller->on_scrolled
+ $on_scrolled = $scroller->on_scrolled;
- $scroller->set_on_scrolled( $on_scrolled )
+ $scroller->set_on_scrolled( $on_scrolled );
Return or set the CODE reference to be called when the scroll position is
adjusted.
- $on_scrolled->( $scroller, $delta )
+ $on_scrolled->( $scroller, $delta );
This is invoked by the C<scroll> method, including the C<scroll_to>,
C<scroll_to_top> and C<scroll_to_bottom>. In normal cases it will be given the
@@ -275,7 +291,7 @@ clipped if this would scroll past the beginning or end of the display.
=head2 items
- $count = scalar $scroller->items;
+ $count = $scroller->items;
I<Since version 0.31.>
@@ -289,7 +305,7 @@ method items { return scalar @_items; }
=head2 push
- $scroller->push( @items )
+ $scroller->push( @items );
Append the given items to the end of the list.
@@ -344,7 +360,7 @@ method push ( @more )
=head2 unshift
- $scroller->unshift( @items )
+ $scroller->unshift( @items );
Prepend the given items to the beginning of the list.
@@ -409,7 +425,7 @@ method unshift ( @more )
=head2 shift
- @items = $scroller->shift( $count )
+ @items = $scroller->shift( $count );
Remove the given number of items from the start of the list and returns them.
@@ -450,7 +466,7 @@ method shift ( $count = 1 )
=head2 pop
- @items = $scroller->pop( $count )
+ @items = $scroller->pop( $count );
Remove the given number of items from the end of the list and returns them.
@@ -488,7 +504,7 @@ method pop ( $count = 1 )
=head2 scroll
- $scroller->scroll( $delta )
+ $scroller->scroll( $delta );
Move the display up or down by the given C<$delta> amount; with positive
moving down. This will be a physical count of displayed lines; if some items
@@ -582,15 +598,16 @@ REDO:
=head2 scroll_to
- $scroller->scroll_to( $line, $itemidx, $itemline )
+ $scroller->scroll_to( $line, $item_or_idx, $itemline );
Moves the display up or down so that display line C<$line> contains line
-C<$itemline> of item C<$itemidx>. Any of these counts may be negative to count
-backwards from the display lines, items, or lines within the item.
+C<$itemline> of the item; which may be given by object reference or index
+number. Any of these counts may be negative to count backwards from the
+display lines, items, or lines within the item.
=cut
-method scroll_to ( $line, $itemidx, $itemline )
+method scroll_to ( $line, $item_or_idx, $itemline )
{
my $window = $self->window or return;
@@ -605,14 +622,7 @@ method scroll_to ( $line, $itemidx, $itemline )
croak '$line out of bounds' if $line >= $_window_lines;
}
- if( $itemidx < 0 ) {
- $itemidx += @_items;
-
- croak '$itemidx out of bounds' if $itemidx < 0;
- }
- else {
- croak '$itemidx out of bounds' if $itemidx >= @_items;
- }
+ my $itemidx = $self->_itemidx_for( $item_or_idx );
my $itemheight = $self->_itemheight( $itemidx );
@@ -663,41 +673,41 @@ method scroll_to ( $line, $itemidx, $itemline )
=head2 scroll_to_top
- $scroller->scroll_to_top( $itemidx, $itemline )
+ $scroller->scroll_to_top( $item_or_idx, $itemline );
Shortcut for C<scroll_to> to set the top line of display; where C<$line> is 0.
-If C<$itemline> is undefined, it will be passed as 0. If C<$itemidx> is also
-undefined, it will be passed as 0. Calling this method with no arguments,
+If C<$itemline> is undefined, it will be passed as 0. If C<$item_or_idx> is
+also undefined, it will be passed as 0. Calling this method with no arguments,
therefore scrolls to the very top of the display.
=cut
-method scroll_to_top ( $itemidx = 0, $itemline = 0 )
+method scroll_to_top ( $item_or_idx = 0, $itemline = 0 )
{
- $self->scroll_to( 0, $itemidx, $itemline );
+ $self->scroll_to( 0, $item_or_idx, $itemline );
}
=head2 scroll_to_bottom
- $scroller->scroll_to_bottom( $itemidx, $itemline )
+ $scroller->scroll_to_bottom( $item_or_idx, $itemline );
Shortcut for C<scroll_to> to set the bottom line of display; where C<$line> is
--1. If C<$itemline> is undefined, it will be passed as -1. If C<$itemidx> is
-also undefined, it will be passed as -1. Calling this method with no
+-1. If C<$itemline> is undefined, it will be passed as -1. If C<$item_or_idx>
+is also undefined, it will be passed as -1. Calling this method with no
arguments, therefore scrolls to the very bottom of the display.
=cut
-method scroll_to_bottom ( $itemidx = -1, $itemline = -1 )
+method scroll_to_bottom ( $item_or_idx = -1, $itemline = -1 )
{
- $self->scroll_to( -1, $itemidx, $itemline );
+ $self->scroll_to( -1, $item_or_idx, $itemline );
}
=head2 line2item
- $itemidx = $scroller->line2item( $line )
+ $itemidx = $scroller->line2item( $line );
- ( $itemidx, $itemline ) = $scroller->line2item( $line )
+ ( $itemidx, $itemline ) = $scroller->line2item( $line );
Returns the item index currently on display at the given line of the window.
In list context, also returns the line number within item. If no window has
@@ -739,14 +749,14 @@ method line2item ( $line )
=head2 item2line
- $line = $scroller->item2line( $itemidx, $itemline )
+ $line = $scroller->item2line( $item_or_idx, $itemline );
- ( $line, $offscreen ) = $scroller->item2line( $itemidx, $itemline, $count_offscreen )
+ ( $line, $offscreen ) = $scroller->item2line( $item_or_idx, $itemline, $count_offscreen );
Returns the display line in the window of the given line of the item at the
-given index. C<$itemidx> may be given negative, to count backwards from the
-last item. C<$itemline> may be negative to count backward from the last line
-of the item.
+given index. C<$item_or_idx> may be an item directly, a non-negative integer
+to give its index, or a negative to count backwards from the last item.
+C<$itemline> may be negative to count backward from the last line of the item.
In list context, also returns a value describing the offscreen nature of the
item. For items fully on display, this value is C<undef>. If the given line of
@@ -759,20 +769,13 @@ lines in the scroller's window for items C<"below">.
=cut
-method item2line ( $want_itemidx, $want_itemline = 0, $count_offscreen = 0 )
+method item2line ( $want_item_or_idx, $want_itemline = 0, $count_offscreen = 0 )
{
my $window = $self->window or return;
@_items or return;
- if( $want_itemidx < 0 ) {
- $want_itemidx += @_items;
-
- croak '$itemidx out of bounds' if $want_itemidx < 0;
- }
- else {
- croak '$itemidx out of bounds' if $want_itemidx >= @_items;
- }
+ my $want_itemidx = $self->_itemidx_for( $want_item_or_idx );
my $itemheight = $self->_itemheight( $want_itemidx );
@@ -827,7 +830,7 @@ method item2line ( $want_itemidx, $want_itemline = 0, $count_offscreen = 0 )
=head2 lines_above
- $count = $scroller->lines_above
+ $count = $scroller->lines_above;
Returns the number of lines of content above the scrolled display.
@@ -842,7 +845,7 @@ method lines_above ()
=head2 lines_below
- $count = $scroller->lines_below
+ $count = $scroller->lines_below;
Returns the number of lines of content below the scrolled display.
@@ -882,7 +885,7 @@ method render_to_rb ( $rb, $rect )
my $endline = $rect->bottom;
while( $line < $endline and $itemidx < @_items ) {
- my $item = $self->_item( $itemidx );
+ my $item = $_items[$itemidx];
my $itemheight = $self->_itemheight( $itemidx );
my $top = $line;
@@ -948,9 +951,9 @@ method on_mouse ( $ev )
=head2 set_gen_bottom_indicator
- $scroller->set_gen_top_indicator( $method )
+ $scroller->set_gen_top_indicator( $method );
- $scroller->set_gen_bottom_indicator( $method )
+ $scroller->set_gen_bottom_indicator( $method );
Accessors for the generators for the top and bottom indicator text. If set,
each should be a CODE reference or method name on the scroller which will be
@@ -960,7 +963,7 @@ if defined and non-empty, will be displayed in an indicator window. This will
be a small one-line window displayed at the top right or bottom right corner
of the Scroller's window.
- $text = $scroller->$method()
+ $text = $scroller->$method();
The ability to pass method names allows subclasses to easily implement custom
logic as methods without having to capture a closure.
@@ -983,7 +986,7 @@ method set_gen_bottom_indicator
=head2 update_indicators
- $scroller->update_indicators
+ $scroller->update_indicators;
Calls any defined generators for indicator text, and updates the indicator
windows with the returned text. This may be useful if the functions would
diff --git a/lib/Tickit/Widget/Scroller/Item/RichText.pm b/lib/Tickit/Widget/Scroller/Item/RichText.pm
index c101041..e5fe349 100644
--- a/lib/Tickit/Widget/Scroller/Item/RichText.pm
+++ b/lib/Tickit/Widget/Scroller/Item/RichText.pm
@@ -1,13 +1,13 @@
# You may distribute under the terms of either the GNU General Public License
# or the Artistic License (the same terms as Perl itself)
#
-# (C) Paul Evans, 2011-2021 -- leonerd@leonerd.org.uk
+# (C) Paul Evans, 2011-2023 -- leonerd@leonerd.org.uk
use v5.26;
use warnings;
-use Object::Pad 0.57;
+use Object::Pad 0.800;
-package Tickit::Widget::Scroller::Item::RichText 0.31;
+package Tickit::Widget::Scroller::Item::RichText 0.32;
class Tickit::Widget::Scroller::Item::RichText
:strict(params)
:isa(Tickit::Widget::Scroller::Item::Text);
@@ -89,6 +89,16 @@ sub new_from_formatting ( $class, $str, %opts )
);
}
+my %PENCACHE;
+method pen_for_tags ( $tags )
+{
+ # Cache the pens
+ my $key = join "|", map { "$_=" . ( $tags->{$_} // "" ) } sort keys %$tags;
+
+ # Don't worry if extra tags left over, they just aren't rendering attributes
+ return $PENCACHE{$key} //= Tickit::Pen::Immutable->new_from_attrs( $tags );
+}
+
method _build_chunks_for ( $str )
{
my @chunks;
@@ -96,8 +106,7 @@ method _build_chunks_for ( $str )
$str->iter_substr_nooverlap(
sub {
my ( $substr, %tags ) = @_;
- my $pen = Tickit::Pen->new_from_attrs( \%tags );
- # Don't worry if extra tags left over, they just aren't rendering attributes
+ my $pen = $self->pen_for_tags( \%tags );
my @lines = split m/\n/, $substr, -1 or return;
my $lastline = pop @lines;
push @chunks, [ $_, textwidth( $_ ), pen => $pen, linebreak => 1 ] for @lines;
diff --git a/lib/Tickit/Widget/Scroller/Item/Text.pm b/lib/Tickit/Widget/Scroller/Item/Text.pm
index 8a514cd..acf0e01 100644
--- a/lib/Tickit/Widget/Scroller/Item/Text.pm
+++ b/lib/Tickit/Widget/Scroller/Item/Text.pm
@@ -5,9 +5,9 @@
use v5.26;
use warnings;
-use Object::Pad 0.70 ':experimental(adjust_params)';
+use Object::Pad 0.800 ':experimental(adjust_params)';
-package Tickit::Widget::Scroller::Item::Text 0.31;
+package Tickit::Widget::Scroller::Item::Text 0.32;
class Tickit::Widget::Scroller::Item::Text
:strict(params);
@@ -42,7 +42,7 @@ the C</\s/> regexp pattern).
=head2 new
- $item = Tickit::Widget::Scroller::Item::Text->new( $text, %opts )
+ $item = Tickit::Widget::Scroller::Item::Text->new( $text, %opts );
Constructs a new text item, containing the given string of text. Once
constructed, the item is immutable.
@@ -112,7 +112,7 @@ ADJUST :params (
=head2 chunks
- @chunks = $item->chunks
+ @chunks = $item->chunks;
Returns the chunks of text displayed by this item. Each chunk is represented
by an ARRAY reference of three fields, giving the text string, its width in
@@ -166,23 +166,23 @@ method height_for_width ( $width )
my ( $text, $textwidth, %opts ) = @$chunk;
if( $textwidth <= $line_remaining ) {
- push @$thisline, [ $text, $textwidth, $opts{pen} ];
+ push @$thisline, [ $text =~ s/\xA0/ /gr, $textwidth, $opts{pen} ];
$line_remaining -= $textwidth;
}
else {
# Split this chunk at most $line_remaining chars
my $eol_ch = cols2chars $text, $line_remaining;
- if( $eol_ch < length $text && substr( $text, $eol_ch, 1 ) =~ m/\S/ ) {
+ if( $eol_ch < length $text && substr( $text, $eol_ch, 1 ) =~ m/[\S\xA0]/ ) {
# TODO: This surely must be possible without substr()ing a temporary
- if( substr( $text, 0, $eol_ch ) =~ m/\S+$/ and
+ if( substr( $text, 0, $eol_ch ) =~ m/[\S\xA0]+$/ and
( $-[0] > 0 or @$thisline ) ) {
$eol_ch = $-[0];
}
}
my $partial_text = substr( $text, 0, $eol_ch );
- my $partial_chunk = [ $partial_text, textwidth( $partial_text ), $opts{pen} ];
+ my $partial_chunk = [ $partial_text =~ s/\xA0/ /gr, textwidth( $partial_text ), $opts{pen} ];
push @$thisline, $partial_chunk;
my $bol_ch = pos $text = $eol_ch;
diff --git a/t/01item-text.t b/t/01item-text.t
index 900c8db..ad9ebd1 100644
--- a/t/01item-text.t
+++ b/t/01item-text.t
@@ -2,6 +2,7 @@
use v5.26;
use warnings;
+use utf8;
use Test2::V0;
@@ -174,8 +175,6 @@ drain_termlog;
# Odd Unicode
{
- use utf8;
-
$term->clear;
drain_termlog;
@@ -203,6 +202,37 @@ drain_termlog;
'Display for render with Unicode' );
}
+# Non-breaking spaces
+{
+ $term->clear;
+ drain_termlog;
+
+ my $item = Tickit::Widget::Scroller::Item::Text->new( "abcdef 12\x{A0}34" );
+
+ is( $item->height_for_width( 11 ), 2, 'height_for_width 2 with NBSP' );
+
+ $item->render( $rb, top => 0, firstline => 0, lastline => 1, width => 11, height => 2 );
+ $rb->flush_to_term( $term );
+
+ flush_tickit;
+
+ is_termlog( [ GOTO(0,0),
+ SETPEN,
+ PRINT("abcdef "),
+ SETPEN,
+ ERASECH(4),
+ GOTO(1,0),
+ SETPEN,
+ PRINT("12 34"),
+ SETPEN,
+ ERASECH(6) ],
+ 'Termlog for render with NBSP' );
+
+ is_display( [ [TEXT("abcdef")],
+ [TEXT("12 34")] ],
+ 'Display for render with NBSP' );
+}
+
# Empty
{
$term->clear;
diff --git a/t/02item-richtext.t b/t/02item-richtext.t
index a1a8ffd..0e379cf 100644
--- a/t/02item-richtext.t
+++ b/t/02item-richtext.t
@@ -25,10 +25,10 @@ isa_ok( $item, [ "Tickit::Widget::Scroller::Item::Text" ], '$item' );
is( [ $item->chunks ],
# Stringify the pens so Test2 will compare the stringified versions
- [ [ "My ", 3, pen => "".Tickit::Pen->new() ],
- [ "message", 7, pen => "".Tickit::Pen->new( b => 1 ) ],
- [ " ", 1, pen => "".Tickit::Pen->new() ],
- [ "here", 4, pen => "".Tickit::Pen->new( u => 1 ) ] ],
+ [ [ "My ", 3, pen => "".Tickit::Pen::Immutable->new() ],
+ [ "message", 7, pen => "".Tickit::Pen::Immutable->new( b => 1 ) ],
+ [ " ", 1, pen => "".Tickit::Pen::Immutable->new() ],
+ [ "here", 4, pen => "".Tickit::Pen::Immutable->new( u => 1 ) ] ],
'$item->chunks' );
is( $item->height_for_width( 80 ), 1, 'height_for_width 80' );
@@ -65,10 +65,10 @@ is_display( [ [TEXT("My "), TEXT("message",b=>1), BLANK(1), TEXT("here",u=>1)] ]
my $item = Tickit::Widget::Scroller::Item::RichText->new( $str );
is( [ $item->chunks ],
- [ [ "Another ", 8, pen => "".Tickit::Pen->new() ],
- [ "message", 7, pen => "".Tickit::Pen->new( b => 1 ), linebreak => 1 ],
- [ "with", 4, pen => "".Tickit::Pen->new( b => 1 ) ],
- [ " linefeeds", 10, pen => "".Tickit::Pen->new() ] ],
+ [ [ "Another ", 8, pen => "".Tickit::Pen::Immutable->new() ],
+ [ "message", 7, pen => "".Tickit::Pen::Immutable->new( b => 1 ), linebreak => 1 ],
+ [ "with", 4, pen => "".Tickit::Pen::Immutable->new( b => 1 ) ],
+ [ " linefeeds", 10, pen => "".Tickit::Pen::Immutable->new() ] ],
'$item->chunks with linefeeds' );
}
diff --git a/t/10initial.t b/t/10initial.t
index be1d567..fdce30a 100644
--- a/t/10initial.t
+++ b/t/10initial.t
@@ -17,7 +17,7 @@ my $scroller = Tickit::Widget::Scroller->new;
ok( defined $scroller, 'defined $scroller' );
$scroller->push(
- map { Tickit::Widget::Scroller::Item::Text->new( $_ ) }
+ my @items = map { Tickit::Widget::Scroller::Item::Text->new( $_ ) }
"The first line",
"Another line in the middle",
"The third line",
@@ -64,6 +64,10 @@ is( $scroller->item2line( 0, -1 ), 0, 'item2line 0, -1' );
is( $scroller->item2line( 1 ), 1, 'item2line 1' );
is( $scroller->item2line( 2 ), 2, 'item2line 2' );
+is( $scroller->item2line( $items[0] ), 0, 'item2line $items[0]' );
+is( $scroller->item2line( $items[1] ), 1, 'item2line $items[1]' );
+is( $scroller->item2line( $items[2] ), 2, 'item2line $items[2]' );
+
is( $scroller->item2line( -1 ), 2, 'item2line -1' );
resize_term( 25, 20 );