summaryrefslogtreecommitdiffstats
path: root/lib/MDK/Common/String.pm
blob: fe2c299c728c916de720460e2235f99742f8d7b5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
package MDK::Common::String;

=head1 NAME

MDK::Common::String - formatting functions

=head1 SYNOPSIS

    use MDK::Common::String qw(:all);

=head1 EXPORTS

=over

=item bestMatchSentence(STRING, LIST)

finds in the list the best corresponding string

=item formatList(INT, LIST)

if the list size is bigger than INT, replace the remaining elements with "...".

formatList(3, qw(a b c d e))  # => "a, b, c, ..."

=item formatError(STRING)

the string is something like "error at foo.pl line 2" that you get when
catching an exception. formatError will remove the "at ..." so that you can
nicely display the returned string to the user

=item formatTimeRaw(TIME)

the TIME is an epoch as returned by C<time>, the formatted time looks like "23:59:00"

=item formatLines(STRING)

remove "\n"s when the next line doesn't start with a space. Otherwise keep
"\n"s to keep the indentation.

=item formatAlaTeX(STRING)

handle carriage return just like LaTeX: merge lines that are not separated by
an empty line

=item begins_with(STRING, STRING)

return true if first argument begins with the second argument. Use this
instead of regexps if you don't want regexps.

begins_with("hello world", "hello")  # => 1

=item warp_text(STRING, INT)

return a list of lines which do not exceed INT characters
(or a string in scalar context)

=item warp_text(STRING)

warp_text at a default width (80)

=back

=head1 SEE ALSO

L<MDK::Common>

=cut


use Exporter;
our @ISA = qw(Exporter);
our @EXPORT_OK = qw(bestMatchSentence formatList formatError formatTimeRaw formatLines formatAlaTeX begins_with warp_text);
our %EXPORT_TAGS = (all => [ @EXPORT_OK ]);


# count the number of character that match
sub bestMatchSentence {

    my $best = -1;
    my $bestSentence;
    my @s = split /\W+/, shift;
    foreach (@_) {
	my $count = 0;
	foreach my $e (@s) {
	    $count += length($e) if /^$e$/;
	    $count += length($e) if /^$e$/i;
	    $count += length($e) if /$e/;
	    $count += length($e) if /$e/i;
	}
	$best = $count, $bestSentence = $_ if $count > $best;
    }
    wantarray() ? ($bestSentence, $best) : $bestSentence;
}


sub formatList {
    my $nb = shift;
    join(", ", @_ <= $nb ? @_ : (@_[0..$nb-1], '...'));
}
sub formatError {
    my ($err) = @_;
    if (!$::testing) {
	$err =~ s/Uncaught exception from user code:\n\t//s; #- happens with "use diagnostics"
	$err =~ s/ at \Q$0\E line .*?$/./s;
    }
    $err;
}
sub formatTimeRaw {
    my ($s, $m, $h) = gmtime($_[0]);
    sprintf "%d:%02d:%02d", $h, $m, $s;
}
sub formatLines {
    my ($t, $tmp);
    foreach (split "\n", $_[0]) {
	if (/^\s/) {
	    $t .= "$tmp\n";
	    $tmp = $_;
	} else {
	    $tmp = ($tmp ? "$tmp " : ($t && "\n") . $tmp) . $_;
	}
    }
    "$t$tmp\n";
}
sub formatAlaTeX {
    my ($t, $tmp) = ('', '');
    foreach (split "\n", $_[0]) {
	if (/^$/) {
	    $t .= ($t && "\n") . $tmp;
	    $tmp = '';
	} else {
	    $tmp = ($tmp && "$tmp ") . (/^\s*(.*?)\s*$/)[0];
	}
    }
    $t . ($t && $tmp && "\n") . $tmp;
}


sub begins_with {
    my ($s, $prefix) = @_;
    index($s, $prefix) == 0;
}

sub warp_text {
    my ($text, $o_width) = @_;

    my @l;
    foreach (split "\n", $text) {
	my ($beg) = /^(\s*)/;
	my $t = '';
	foreach (split /\s+/, $_) {
	    if (length "$beg$t $_" > ($o_width || 80)) {
		push @l, "$beg$t";
                $beg = '';
		$t = $_;
	    } else {
		$t = $t ? "$t $_" : $_;
	    }
	}
	push @l, "$beg$t";
    }
    wantarray() ? @l : join("\n", @l);
}

1;