File Coverage

blib/lib/Alice/Window.pm
Criterion Covered Total %
statement 40 88 45.4
branch 2 16 12.5
condition 0 5 0.0
subroutine 14 25 56.0
pod 0 17 0.0
total 56 151 37.0


line stmt bran cond sub pod time code
1             package Alice::Window;
2              
3 2     2   10 use Encode;
  2         2  
  2         164  
4 2     2   1943 use utf8;
  2         19  
  2         12  
5 2     2   967 use Alice::MessageBuffer;
  2         6  
  2         63  
6 2     2   15 use Text::MicroTemplate qw/encoded_string/;
  2         4  
  2         133  
7 2     2   12 use IRC::Formatting::HTML qw/irc_to_html/;
  2         3  
  2         82  
8 2     2   11 use Any::Moose;
  2         4  
  2         10  
9 2     2   933 use AnyEvent;
  2         4  
  2         362  
10              
11 2     2   11 my $url_regex = qr/\b(https?:\/\/(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:'".,<>?«»“”‘’]))/i;
  2         3  
  2         27  
12              
13             has buffer => (
14             is => 'rw',
15             required => 1,
16             );
17              
18             has title => (
19             is => 'ro',
20             isa => 'Str',
21             required => 1,
22             );
23              
24             has topic => (
25             is => 'rw',
26             isa => 'HashRef[Str|Undef]',
27             default => sub {{
28             string => 'no topic set',
29             author => '',
30             time => time,
31             }}
32             );
33              
34             has id => (
35             is => 'ro',
36             required => 1,
37             );
38              
39             has disabled => (
40             is => 'rw',
41             default => 0,
42             );
43              
44             has render => (
45             is => 'ro',
46             required => 1,
47             );
48              
49             sub sort_name {
50 1     1 0 14 my $name = lc $_[0]->title;
51 1         11 $name =~ s/^[^\w\d]+//;
52 1         31 $name;
53             }
54              
55             sub pretty_name {
56 0     0 0 0 my $self = shift;
57 0 0       0 if ($self->is_channel) {
58 0         0 return substr $self->title, 1;
59             }
60 0         0 return $self->title;
61             }
62              
63             has type => (
64             is => 'ro',
65             required => 1,
66             );
67              
68             has network => (
69             is => 'ro',
70             required => 1,
71             );
72              
73 5     5 0 41 sub is_channel {$_[0]->type eq "channel"}
74              
75             sub topic_string {
76 2     2 0 11 my $self = shift;
77 2 50       19 if ($self->is_channel) {
78 0   0     0 return $self->topic->{string} || $self->title . ": no topic set";
79             }
80 2         79 return $self->title;
81             }
82              
83             sub serialized {
84 2     2 0 12 my ($self) = @_;
85             return {
86 2         59 id => $self->id,
87             network => $self->network,
88             title => $self->title,
89             is_channel => $self->is_channel,
90             type => $self->type,
91             hashtag => $self->hashtag,
92             topic => $self->topic_string,
93             };
94             }
95              
96             sub join_action {
97 0     0 0 0 my $self = shift;
98             return {
99 0         0 type => "action",
100             event => "join",
101             window => $self->serialized,
102             html => {
103             window => $self->render->("window", $self),
104             tab => $self->render->("tab", $self),
105             },
106             };
107             }
108              
109             sub nicks_action {
110 0     0 0 0 my ($self, @nicks) = @_;
111             return {
112 0         0 type => "action",
113             event => "nicks",
114             nicks => \@nicks,
115             window => $self->serialized,
116             };
117             }
118              
119             sub clear_action {
120 0     0 0 0 my $self = shift;
121             return {
122 0         0 type => "action",
123             event => "clear",
124             window => $self->serialized,
125             };
126             }
127              
128             sub format_event {
129 0     0 0 0 my ($self, $event, $nick, $body) = @_;
130 0         0 my $message = {
131             type => "message",
132             event => $event,
133             nick => $nick,
134             window => $self->serialized,
135             body => $body,
136             msgid => $self->buffer->next_msgid,
137             timestamp => time,
138             };
139              
140 0         0 my $html = $self->render->("event", $message);
141 0         0 $message->{html} = $html;
142              
143 0         0 $self->buffer->add($message);
144 0         0 return $message;
145             }
146              
147             sub format_topic {
148 0     0 0 0 my $self = shift;
149 0   0     0 return $self->format_event("topic", $self->topic->{author} || "", $self->topic_string);
150             }
151              
152             sub format_message {
153 0     0 0 0 my ($self, $nick, $body, %options) = @_;
154              
155             # pass the inverse => italic option if this is NOT monospace
156 0 0       0 my $html = irc_to_html($body, classes => 1, ($options{monospaced} ? () : (invert => "italic")));
157              
158 0         0 my $message = {
159             type => "message",
160             event => "say",
161             nick => $nick,
162             window => $self->serialized,
163             html => encoded_string($html),
164             msgid => $self->buffer->next_msgid,
165             timestamp => time,
166             consecutive => $nick eq $self->buffer->previous_nick,
167             %options,
168             };
169              
170 0         0 $message->{html} = $self->render->("message", $message);
171              
172 0         0 $self->buffer->add($message);
173 0         0 return $message;
174             }
175              
176             sub close_action {
177 1     1 0 3 my $self = shift;
178             return +{
179 1         5 type => "action",
180             event => "part",
181             window => $self->serialized,
182             };
183             }
184              
185             sub trim_action {
186 0     0 0 0 my ($self, $lines) = @_;
187             return +{
188 0         0 type => "action",
189             event => "trim",
190             lines => $lines,
191             window => $self->serialized,
192             };
193             }
194              
195             sub nick_table {
196 0     0 0 0 my ($self, @nicks) = @_;
197              
198 0 0       0 return "" unless @nicks;
199              
200 0         0 my $maxlen = 0;
201 0         0 for (@nicks) {
202 0         0 my $length = length $_;
203 0 0       0 $maxlen = $length if $length > $maxlen;
204             }
205 0         0 my $cols = int(74 / $maxlen + 2);
206 0         0 my (@rows, @row);
207 0         0 for (sort {lc $a cmp lc $b} @nicks) {
  0         0  
208 0         0 push @row, $_ . " " x ($maxlen - length $_);
209 0 0       0 if (@row >= $cols) {
210 0         0 push @rows, [@row];
211 0         0 @row = ();
212             }
213             }
214 0 0       0 push @rows, [@row] if @row;
215 0         0 return join "\n", map {join " ", @$_} @rows;
  0         0  
216             }
217              
218             sub reset_previous_nick {
219 0     0 0 0 my $self = shift;
220 0         0 $self->buffer->previous_nick("");
221             }
222              
223             sub previous_nick {
224 0     0 0 0 my $self = shift;
225 0         0 return $self->buffer->previous_nick;
226             }
227              
228             sub hashtag {
229 1     1 0 3 my $self = shift;
230              
231 1         4 my $name = $self->title;
232 1         16 $name =~ s/[#&~@]//g;
233 1 50       15 my $path = $self->type eq "privmsg" ? "users" : "channels";
234            
235 1         11 return "/" . $self->network . "/$path/" . $name;
236             }
237              
238             __PACKAGE__->meta->make_immutable;
239             1;