|
@@ -3,9 +3,9 @@
|
|
%%% @author Roberto Saccon <rsaccon@gmail.com> [http://rsaccon.com]
|
|
%%% @author Roberto Saccon <rsaccon@gmail.com> [http://rsaccon.com]
|
|
%%% @author Evan Miller <emmiller@gmail.com>
|
|
%%% @author Evan Miller <emmiller@gmail.com>
|
|
%%% @copyright 2008 Roberto Saccon, Evan Miller
|
|
%%% @copyright 2008 Roberto Saccon, Evan Miller
|
|
-%%% @doc
|
|
|
|
|
|
+%%% @doc
|
|
%%% Template filters
|
|
%%% Template filters
|
|
-%%% @end
|
|
|
|
|
|
+%%% @end
|
|
%%%
|
|
%%%
|
|
%%% The MIT License
|
|
%%% The MIT License
|
|
%%%
|
|
%%%
|
|
@@ -42,82 +42,93 @@
|
|
-include_lib("eunit/include/eunit.hrl").
|
|
-include_lib("eunit/include/eunit.hrl").
|
|
|
|
|
|
-ifdef(TEST).
|
|
-ifdef(TEST).
|
|
- -export([cast_to_float/1,cast_to_integer/1,stringformat_io/7,round/2,unjoin/2]).
|
|
|
|
|
|
+ -export([cast_to_float/1,cast_to_integer/1,stringformat_io/7,round/2,unjoin/2,addDefaultURI/1]).
|
|
-endif.
|
|
-endif.
|
|
|
|
|
|
-
|
|
|
|
--export([add/2,
|
|
|
|
|
|
+
|
|
|
|
+-export([add/2,
|
|
addslashes/1,
|
|
addslashes/1,
|
|
- capfirst/1,
|
|
|
|
- center/2,
|
|
|
|
|
|
+ capfirst/1,
|
|
|
|
+ center/2,
|
|
cut/2,
|
|
cut/2,
|
|
- date/2,
|
|
|
|
|
|
+ date/2,
|
|
default/2,
|
|
default/2,
|
|
- default_if_none/2,
|
|
|
|
- %dictsort/,
|
|
|
|
- %dictsortreversed/,
|
|
|
|
|
|
+ default_if_none/2,
|
|
|
|
+ dictsort/2,
|
|
|
|
+ dictsortreversed/2,
|
|
divisibleby/2,
|
|
divisibleby/2,
|
|
%escape/,
|
|
%escape/,
|
|
escapejs/1,
|
|
escapejs/1,
|
|
filesizeformat/1,
|
|
filesizeformat/1,
|
|
- first/1,
|
|
|
|
- fix_ampersands/1,
|
|
|
|
|
|
+ first/1,
|
|
|
|
+ fix_ampersands/1,
|
|
floatformat/2,
|
|
floatformat/2,
|
|
- force_escape/1,
|
|
|
|
- format_integer/1,
|
|
|
|
|
|
+ force_escape/1,
|
|
|
|
+ format_integer/1,
|
|
format_number/1,
|
|
format_number/1,
|
|
get_digit/2,
|
|
get_digit/2,
|
|
%iriencode/1,
|
|
%iriencode/1,
|
|
- join/2,
|
|
|
|
- last/1,
|
|
|
|
- length/1,
|
|
|
|
- length_is/2,
|
|
|
|
|
|
+ join/2,
|
|
|
|
+ last/1,
|
|
|
|
+ length/1,
|
|
|
|
+ length_is/2,
|
|
linebreaks/1,
|
|
linebreaks/1,
|
|
- linebreaksbr/1,
|
|
|
|
|
|
+ linebreaksbr/1,
|
|
linenumbers/1,
|
|
linenumbers/1,
|
|
ljust/2,
|
|
ljust/2,
|
|
- lower/1,
|
|
|
|
|
|
+ lower/1,
|
|
make_list/1,
|
|
make_list/1,
|
|
phone2numeric/1,
|
|
phone2numeric/1,
|
|
pluralize/1,
|
|
pluralize/1,
|
|
pluralize/2,
|
|
pluralize/2,
|
|
- %pprint/,
|
|
|
|
|
|
+ pprint/1,
|
|
random/1,
|
|
random/1,
|
|
random_num/1,
|
|
random_num/1,
|
|
random_range/1,
|
|
random_range/1,
|
|
removetags/2,
|
|
removetags/2,
|
|
- rjust/2,
|
|
|
|
|
|
+ rjust/2,
|
|
%safe/,
|
|
%safe/,
|
|
%safeseq/,
|
|
%safeseq/,
|
|
slice/2,
|
|
slice/2,
|
|
slugify/1,
|
|
slugify/1,
|
|
stringformat/2,
|
|
stringformat/2,
|
|
- %striptags/,
|
|
|
|
|
|
+ striptags/1,
|
|
|
|
+ time/1,
|
|
time/2,
|
|
time/2,
|
|
- %timesince/,
|
|
|
|
- %timeuntil/,
|
|
|
|
|
|
+ timesince/1,
|
|
|
|
+ timesince/2,
|
|
|
|
+ timeuntil/1,
|
|
|
|
+ timeuntil/2,
|
|
title/1,
|
|
title/1,
|
|
- truncatewords/2,
|
|
|
|
|
|
+ truncatewords/2,
|
|
%truncatewords_html/,
|
|
%truncatewords_html/,
|
|
- %unordered_list/,
|
|
|
|
- upper/1,
|
|
|
|
|
|
+ %unordered_list/1,
|
|
|
|
+ upper/1,
|
|
urlencode/1,
|
|
urlencode/1,
|
|
- %urlize/,
|
|
|
|
- %urlizetrunc/,
|
|
|
|
|
|
+ urlize/1,
|
|
|
|
+ urlize/2,
|
|
|
|
+ urlizetrunc/2,
|
|
wordcount/1,
|
|
wordcount/1,
|
|
wordwrap/2,
|
|
wordwrap/2,
|
|
yesno/2]).
|
|
yesno/2]).
|
|
-
|
|
|
|
|
|
+
|
|
-define(NO_ENCODE(C), ((C >= $a andalso C =< $z) orelse
|
|
-define(NO_ENCODE(C), ((C >= $a andalso C =< $z) orelse
|
|
(C >= $A andalso C =< $Z) orelse
|
|
(C >= $A andalso C =< $Z) orelse
|
|
(C >= $0 andalso C =< $9) orelse
|
|
(C >= $0 andalso C =< $9) orelse
|
|
- (C =:= $\. orelse C =:= $-
|
|
|
|
|
|
+ (C =:= $\. orelse C =:= $-
|
|
orelse C =:= $~ orelse C =:= $_))).
|
|
orelse C =:= $~ orelse C =:= $_))).
|
|
-
|
|
|
|
|
|
+
|
|
-define(KILOBYTE, 1024).
|
|
-define(KILOBYTE, 1024).
|
|
-define(MEGABYTE, (1024 * ?KILOBYTE)).
|
|
-define(MEGABYTE, (1024 * ?KILOBYTE)).
|
|
-define(GIGABYTE, (1024 * ?MEGABYTE)).
|
|
-define(GIGABYTE, (1024 * ?MEGABYTE)).
|
|
|
|
|
|
|
|
+-define(SECONDS_PER_MINUTE, 60).
|
|
|
|
+-define(SECONDS_PER_HOUR, (60 * ?SECONDS_PER_MINUTE)).
|
|
|
|
+-define(SECONDS_PER_DAY, (24 * ?SECONDS_PER_HOUR)).
|
|
|
|
+-define(SECONDS_PER_WEEK, (7 * ?SECONDS_PER_DAY)).
|
|
|
|
+-define(SECONDS_PER_MONTH, (30 * ?SECONDS_PER_DAY)).
|
|
|
|
+-define(SECONDS_PER_YEAR, (365 * ?SECONDS_PER_DAY)).
|
|
|
|
+
|
|
%% @doc Adds a number to the value.
|
|
%% @doc Adds a number to the value.
|
|
add(Input, Number) when is_binary(Input) ->
|
|
add(Input, Number) when is_binary(Input) ->
|
|
list_to_binary(add(binary_to_list(Input), Number));
|
|
list_to_binary(add(binary_to_list(Input), Number));
|
|
@@ -125,31 +136,35 @@ add(Input, Number) when is_list(Input) ->
|
|
integer_to_list(add(list_to_integer(Input), Number));
|
|
integer_to_list(add(list_to_integer(Input), Number));
|
|
add(Input, Number) when is_integer(Input) ->
|
|
add(Input, Number) when is_integer(Input) ->
|
|
Input + Number.
|
|
Input + Number.
|
|
-
|
|
|
|
|
|
+
|
|
%% @doc Adds slashes before quotes.
|
|
%% @doc Adds slashes before quotes.
|
|
addslashes(Input) when is_binary(Input) ->
|
|
addslashes(Input) when is_binary(Input) ->
|
|
addslashes(binary_to_list(Input));
|
|
addslashes(binary_to_list(Input));
|
|
addslashes(Input) when is_list(Input) ->
|
|
addslashes(Input) when is_list(Input) ->
|
|
addslashes(Input, []).
|
|
addslashes(Input, []).
|
|
-
|
|
|
|
|
|
+
|
|
%% @doc Capitalizes the first character of the value.
|
|
%% @doc Capitalizes the first character of the value.
|
|
capfirst([H|T]) when H >= $a andalso H =< $z ->
|
|
capfirst([H|T]) when H >= $a andalso H =< $z ->
|
|
[H + $A - $a | T];
|
|
[H + $A - $a | T];
|
|
|
|
+capfirst(Other) when is_list(Other) ->
|
|
|
|
+ Other;
|
|
capfirst(<<Byte:8/integer, Binary/binary>>) when Byte >= $a andalso Byte =< $z ->
|
|
capfirst(<<Byte:8/integer, Binary/binary>>) when Byte >= $a andalso Byte =< $z ->
|
|
- [(Byte + $A - $a)|binary_to_list(Binary)].
|
|
|
|
-
|
|
|
|
|
|
+ [(Byte + $A - $a)|binary_to_list(Binary)];
|
|
|
|
+capfirst(Other) when is_binary(Other) ->
|
|
|
|
+ Other.
|
|
|
|
+
|
|
%% @doc Centers the value in a field of a given width.
|
|
%% @doc Centers the value in a field of a given width.
|
|
center(Input, Number) when is_binary(Input) ->
|
|
center(Input, Number) when is_binary(Input) ->
|
|
list_to_binary(center(binary_to_list(Input), Number));
|
|
list_to_binary(center(binary_to_list(Input), Number));
|
|
center(Input, Number) when is_list(Input) ->
|
|
center(Input, Number) when is_list(Input) ->
|
|
string:centre(Input, Number).
|
|
string:centre(Input, Number).
|
|
-
|
|
|
|
|
|
+
|
|
%% @doc Removes all values of arg from the given string.
|
|
%% @doc Removes all values of arg from the given string.
|
|
cut(Input, Arg) when is_binary(Input) ->
|
|
cut(Input, Arg) when is_binary(Input) ->
|
|
cut(binary_to_list(Input), Arg);
|
|
cut(binary_to_list(Input), Arg);
|
|
cut(Input, [Char]) when is_list(Input) ->
|
|
cut(Input, [Char]) when is_list(Input) ->
|
|
cut(Input, Char, []).
|
|
cut(Input, Char, []).
|
|
-
|
|
|
|
|
|
+
|
|
%% @doc Formats a date according to the given format.
|
|
%% @doc Formats a date according to the given format.
|
|
date(Input, FormatStr) when is_binary(Input) ->
|
|
date(Input, FormatStr) when is_binary(Input) ->
|
|
list_to_binary(date(binary_to_list(Input), FormatStr));
|
|
list_to_binary(date(binary_to_list(Input), FormatStr));
|
|
@@ -176,6 +191,17 @@ default_if_none(undefined, Default) ->
|
|
default_if_none(Input, _) ->
|
|
default_if_none(Input, _) ->
|
|
Input.
|
|
Input.
|
|
|
|
|
|
|
|
+%% @doc Takes a list of dictionaries and returns that list sorted by the key given in the argument.
|
|
|
|
+dictsort(DictList, Key) ->
|
|
|
|
+ case lists:all(fun(Dict) -> dict:is_key(Key, Dict) end, DictList) of
|
|
|
|
+ true -> lists:sort(fun(K1,K2) -> dict:find(Key,K1) =< dict:find(Key,K2) end, DictList);
|
|
|
|
+ false -> error
|
|
|
|
+ end.
|
|
|
|
+
|
|
|
|
+%% @doc Same as dictsort, but the list is reversed.
|
|
|
|
+dictsortreversed(DictList, Key) ->
|
|
|
|
+ lists:reverse(dictsort(DictList, Key)).
|
|
|
|
+
|
|
%% @doc Returns `true' if the value is divisible by the argument.
|
|
%% @doc Returns `true' if the value is divisible by the argument.
|
|
divisibleby(Input, Divisor) when is_binary(Input) ->
|
|
divisibleby(Input, Divisor) when is_binary(Input) ->
|
|
divisibleby(binary_to_list(Input), Divisor);
|
|
divisibleby(binary_to_list(Input), Divisor);
|
|
@@ -186,8 +212,6 @@ divisibleby(Input, Divisor) when is_list(Divisor) ->
|
|
divisibleby(Input, Divisor) when is_integer(Input), is_integer(Divisor) ->
|
|
divisibleby(Input, Divisor) when is_integer(Input), is_integer(Divisor) ->
|
|
Input rem Divisor =:= 0.
|
|
Input rem Divisor =:= 0.
|
|
|
|
|
|
-%% @doc Escapes
|
|
|
|
-
|
|
|
|
%% @doc Escapes characters for use in JavaScript strings.
|
|
%% @doc Escapes characters for use in JavaScript strings.
|
|
escapejs(Input) when is_binary(Input) ->
|
|
escapejs(Input) when is_binary(Input) ->
|
|
escapejs(binary_to_list(Input));
|
|
escapejs(binary_to_list(Input));
|
|
@@ -225,7 +249,7 @@ fix_ampersands(Input) when is_list(Input) ->
|
|
floatformat(Number, Place) when is_binary(Number) ->
|
|
floatformat(Number, Place) when is_binary(Number) ->
|
|
floatformat(binary_to_list(Number), Place);
|
|
floatformat(binary_to_list(Number), Place);
|
|
floatformat(Number, Place) ->
|
|
floatformat(Number, Place) ->
|
|
- floatformat_io(Number, Place).
|
|
|
|
|
|
+ floatformat_io(Number, cast_to_integer(Place)).
|
|
|
|
|
|
floatformat_io(Number, []) ->
|
|
floatformat_io(Number, []) ->
|
|
floatformat_io(Number, -1);
|
|
floatformat_io(Number, -1);
|
|
@@ -249,7 +273,7 @@ floatformat_io(Number, Precision) when Precision < 0 ->
|
|
round(Number, Precision) ->
|
|
round(Number, Precision) ->
|
|
P = math:pow(10, Precision),
|
|
P = math:pow(10, Precision),
|
|
round(Number * P) / P.
|
|
round(Number * P) / P.
|
|
-
|
|
|
|
|
|
+
|
|
%% @doc Applies HTML escaping to a string.
|
|
%% @doc Applies HTML escaping to a string.
|
|
force_escape(Input) when is_list(Input) ->
|
|
force_escape(Input) when is_list(Input) ->
|
|
escape(Input, []);
|
|
escape(Input, []);
|
|
@@ -332,44 +356,20 @@ linebreaksbr(Input) ->
|
|
linebreaksbr(Input, []).
|
|
linebreaksbr(Input, []).
|
|
|
|
|
|
%% @doc Displays text with line numbers.
|
|
%% @doc Displays text with line numbers.
|
|
-%% probably slow implementation
|
|
|
|
linenumbers(Input) when is_binary(Input) ->
|
|
linenumbers(Input) when is_binary(Input) ->
|
|
- linenumbers(binary_to_list(Input));
|
|
|
|
|
|
+ linenumbers(binary_to_list(Input));
|
|
linenumbers(Input) when is_list(Input) ->
|
|
linenumbers(Input) when is_list(Input) ->
|
|
- linenumbers_io(Input, [], 1).
|
|
|
|
-
|
|
|
|
-%linenumbers_io(Input) ->
|
|
|
|
-% Lines = string:tokens(Input, "\n"),
|
|
|
|
-% Numbers = lists:seq(1, erlang:length(Lines)),
|
|
|
|
-% lists:concat(lists:zipwith(fun(Number, Line) -> erlang:integer_to_list(Number) ++ ". " ++ Line ++ "\n" end, Numbers, Lines)).
|
|
|
|
-
|
|
|
|
-%linenumbers(Input) ->
|
|
|
|
-% linenumbers_io(Input, [], 1).
|
|
|
|
|
|
+ linenumbers_io(Input, [], 1).
|
|
|
|
|
|
linenumbers_io([], Acc, _) ->
|
|
linenumbers_io([], Acc, _) ->
|
|
lists:reverse(Acc);
|
|
lists:reverse(Acc);
|
|
linenumbers_io(Input, [], LineNumber) ->
|
|
linenumbers_io(Input, [], LineNumber) ->
|
|
- linenumbers_io(Input,
|
|
|
|
- lists:reverse(integer_to_list(LineNumber)++". "), LineNumber + 1);
|
|
|
|
|
|
+ linenumbers_io(Input, lists:reverse(integer_to_list(LineNumber)++". "), LineNumber + 1);
|
|
linenumbers_io("\n"++Rest, Acc, LineNumber) ->
|
|
linenumbers_io("\n"++Rest, Acc, LineNumber) ->
|
|
- linenumbers_io(Rest, lists:reverse("\n" ++ integer_to_list(LineNumber) ++ ". ") ++ Acc, LineNumber + 1);
|
|
|
|
|
|
+ linenumbers_io(Rest, lists:reverse("\n" ++ integer_to_list(LineNumber) ++ ". ", Acc), LineNumber + 1);
|
|
linenumbers_io([H|T], Acc, LineNumber) ->
|
|
linenumbers_io([H|T], Acc, LineNumber) ->
|
|
- linenumbers_io(T, [H|Acc], LineNumber).
|
|
|
|
-
|
|
|
|
-%% @doc Displays text with line numbers.
|
|
|
|
-%% tail recursive implementation
|
|
|
|
-%% linenumbers(Input) when is_binary(Input) ->
|
|
|
|
-%% linenumbers_io(binary_to_list(Input), [], 0);
|
|
|
|
-%% linenumbers(Input) when is_list(Input) ->
|
|
|
|
-%% linenumbers_io(Input, [], 0).
|
|
|
|
-%%
|
|
|
|
-%% linenumbers([], Acc, ) ->
|
|
|
|
-%% lists:reverse(Acc);
|
|
|
|
-%% linenumbers([Head|Rest], Acc, CountAcc) ->
|
|
|
|
-%% Count = CountAcc + 1,
|
|
|
|
-%% LineNumber = integer_to_list(Count) ++ ". ",
|
|
|
|
-%% linenumbers(Rest, lists:append(LineNumber, Acc));
|
|
|
|
-
|
|
|
|
|
|
+ linenumbers_io(T, [H|Acc], LineNumber).
|
|
|
|
+
|
|
%% @doc Left-aligns the value in a field of a given width.
|
|
%% @doc Left-aligns the value in a field of a given width.
|
|
ljust(Input, Number) when is_binary(Input) ->
|
|
ljust(Input, Number) when is_binary(Input) ->
|
|
list_to_binary(ljust(binary_to_list(Input), Number));
|
|
list_to_binary(ljust(binary_to_list(Input), Number));
|
|
@@ -389,7 +389,7 @@ make_list(Input) when is_binary(Input) ->
|
|
make_list(binary_to_list(Input));
|
|
make_list(binary_to_list(Input));
|
|
make_list(Input) ->
|
|
make_list(Input) ->
|
|
unjoin(Input,"").
|
|
unjoin(Input,"").
|
|
-
|
|
|
|
|
|
+
|
|
%% @doc Converts a phone number (possibly containing letters) to its numerical equivalent.
|
|
%% @doc Converts a phone number (possibly containing letters) to its numerical equivalent.
|
|
phone2numeric(Input) when is_binary(Input) ->
|
|
phone2numeric(Input) when is_binary(Input) ->
|
|
phone2numeric(binary_to_list(Input));
|
|
phone2numeric(binary_to_list(Input));
|
|
@@ -398,33 +398,34 @@ phone2numeric(Input) when is_list(Input) ->
|
|
|
|
|
|
%% @doc Returns a plural suffix if the value is not 1. By default, this suffix is 's'.
|
|
%% @doc Returns a plural suffix if the value is not 1. By default, this suffix is 's'.
|
|
pluralize(Number, Suffix) when is_binary(Suffix) ->
|
|
pluralize(Number, Suffix) when is_binary(Suffix) ->
|
|
- pluralize_io(Number, binary_to_list(Suffix) );
|
|
|
|
|
|
+ pluralize_io(Number, binary_to_list(Suffix) );
|
|
pluralize(Number, Suffix) when is_list(Suffix) ->
|
|
pluralize(Number, Suffix) when is_list(Suffix) ->
|
|
- pluralize_io(Number, Suffix).
|
|
|
|
-
|
|
|
|
|
|
+ pluralize_io(Number, Suffix).
|
|
|
|
+
|
|
pluralize(Number) ->
|
|
pluralize(Number) ->
|
|
- pluralize(Number, "s").
|
|
|
|
-
|
|
|
|
|
|
+ pluralize(Number, "s").
|
|
|
|
+
|
|
pluralize_io(Number, Suffix) ->
|
|
pluralize_io(Number, Suffix) ->
|
|
-%% io:format("Number, Suffix: ~p, ~p ~n", [Number, Suffix]),
|
|
|
|
- case lists:member($, , Suffix) of
|
|
|
|
- true ->
|
|
|
|
- [Singular, Plural] = string:tokens(Suffix,","),
|
|
|
|
- case Number > 1 of
|
|
|
|
- false ->
|
|
|
|
- Singular;
|
|
|
|
- true ->
|
|
|
|
- Plural
|
|
|
|
- end;
|
|
|
|
- false ->
|
|
|
|
- case Number > 1 of
|
|
|
|
- false ->
|
|
|
|
- [];
|
|
|
|
- true ->
|
|
|
|
- Suffix
|
|
|
|
- end
|
|
|
|
- end.
|
|
|
|
-
|
|
|
|
|
|
+ case lists:member($, , Suffix) of
|
|
|
|
+ true ->
|
|
|
|
+ [Singular, Plural] = string:tokens(Suffix,","),
|
|
|
|
+ case Number of
|
|
|
|
+ 0 -> Plural;
|
|
|
|
+ 1 -> Singular;
|
|
|
|
+ _ -> Plural
|
|
|
|
+ end;
|
|
|
|
+ false ->
|
|
|
|
+ case Number of
|
|
|
|
+ 0 -> Suffix;
|
|
|
|
+ 1 -> [];
|
|
|
|
+ _ -> Suffix
|
|
|
|
+ end
|
|
|
|
+ end.
|
|
|
|
+
|
|
|
|
+%% @doc "pretty print" arbitrary data structures. Used for debugging.
|
|
|
|
+pprint(Input) ->
|
|
|
|
+ io_lib:format("~p",[Input]).
|
|
|
|
+
|
|
%% @doc Returns a random item from the given list.
|
|
%% @doc Returns a random item from the given list.
|
|
random(Input) when is_list(Input) ->
|
|
random(Input) when is_list(Input) ->
|
|
lists:nth(random:uniform(erlang:length(Input)), Input);
|
|
lists:nth(random:uniform(erlang:length(Input)), Input);
|
|
@@ -458,7 +459,7 @@ removetags(Input, Tags) ->
|
|
Regex = lists:flatten(io_lib:format("</?(~s)( |\n)?>",[TagListString])),
|
|
Regex = lists:flatten(io_lib:format("</?(~s)( |\n)?>",[TagListString])),
|
|
Result = re:replace(Input,Regex,"", [global,{return,list}]),
|
|
Result = re:replace(Input,Regex,"", [global,{return,list}]),
|
|
Result.
|
|
Result.
|
|
-
|
|
|
|
|
|
+
|
|
%% @doc Right-aligns the value in a field of a given width.
|
|
%% @doc Right-aligns the value in a field of a given width.
|
|
rjust(Input, Number) when is_binary(Input) ->
|
|
rjust(Input, Number) when is_binary(Input) ->
|
|
list_to_binary(rjust(binary_to_list(Input), Number));
|
|
list_to_binary(rjust(binary_to_list(Input), Number));
|
|
@@ -467,23 +468,23 @@ rjust(Input, Number) ->
|
|
|
|
|
|
%% @doc Returns a slice of the list.
|
|
%% @doc Returns a slice of the list.
|
|
slice(Input, Index) when is_binary(Input) ->
|
|
slice(Input, Index) when is_binary(Input) ->
|
|
- erlydtl_slice:slice(binary_to_list(Input), Index);
|
|
|
|
|
|
+ erlydtl_slice:slice(binary_to_list(Input), Index);
|
|
slice(Input, Index) when is_list(Input) ->
|
|
slice(Input, Index) when is_list(Input) ->
|
|
- erlydtl_slice:slice(Input, Index).
|
|
|
|
|
|
+ erlydtl_slice:slice(Input, Index).
|
|
|
|
|
|
%% regex " ^([#0-\s+].)([0-9\*]+)(\.[0-9]+)([diouxXeEfFgGcrs]) " matches ALL of "-10.0f"
|
|
%% regex " ^([#0-\s+].)([0-9\*]+)(\.[0-9]+)([diouxXeEfFgGcrs]) " matches ALL of "-10.0f"
|
|
%% ([#0-\s+]?)([0-9\*]+)?(\.?)([0-9]?)([diouxXeEfFgGcrs])
|
|
%% ([#0-\s+]?)([0-9\*]+)?(\.?)([0-9]?)([diouxXeEfFgGcrs])
|
|
%% @doc Returns a formatted string
|
|
%% @doc Returns a formatted string
|
|
stringformat(Input, Conversion) when is_binary(Input) ->
|
|
stringformat(Input, Conversion) when is_binary(Input) ->
|
|
- stringformat(binary_to_list(Input), Conversion);
|
|
|
|
|
|
+ stringformat(binary_to_list(Input), Conversion);
|
|
stringformat(Input, Conversion) ->
|
|
stringformat(Input, Conversion) ->
|
|
- ParsedConversion = re:replace(Conversion, "([\-#\+ ]?)([0-9\*]+)?(\.?)([0-9]?)([diouxXeEfFgGcrs])", "\\1 ,\\2 ,\\3 ,\\4 ,\\5 ", [{return,list}]),
|
|
|
|
- ?debugFmt("ParsedConversion: ~p~n", [ParsedConversion]),
|
|
|
|
- ParsedConversion1 = lists:map(fun(X) -> string:strip(X) end, string:tokens(ParsedConversion, ",")),
|
|
|
|
- [ConversionFlag, MinFieldWidth, Precision, PrecisionLength, ConversionType] = ParsedConversion1,
|
|
|
|
- ?debugFmt("ConversionFlag, MinFieldWidth, Precision, PrecisionLength, ConversionType: ~p, ~p, ~p, ~p, ~p ~n", [ConversionFlag, cast_to_integer(MinFieldWidth), Precision, cast_to_integer(PrecisionLength), ConversionType]),
|
|
|
|
- [String] = stringformat_io(Input, Conversion, ConversionFlag, cast_to_integer(MinFieldWidth), Precision, cast_to_integer(PrecisionLength), ConversionType),
|
|
|
|
- lists:flatten(String).
|
|
|
|
|
|
+ ParsedConversion = re:replace(Conversion, "([\-#\+ ]?)([0-9\*]+)?(\.?)([0-9]?)([diouxXeEfFgGcrs])", "\\1 ,\\2 ,\\3 ,\\4 ,\\5 ", [{return,list}]),
|
|
|
|
+ ?debugFmt("ParsedConversion: ~p~n", [ParsedConversion]),
|
|
|
|
+ ParsedConversion1 = lists:map(fun(X) -> string:strip(X) end, string:tokens(ParsedConversion, ",")),
|
|
|
|
+ [ConversionFlag, MinFieldWidth, Precision, PrecisionLength, ConversionType] = ParsedConversion1,
|
|
|
|
+ ?debugFmt("ConversionFlag, MinFieldWidth, Precision, PrecisionLength, ConversionType: ~p, ~p, ~p, ~p, ~p ~n", [ConversionFlag, cast_to_integer(MinFieldWidth), Precision, cast_to_integer(PrecisionLength), ConversionType]),
|
|
|
|
+ [String] = stringformat_io(Input, Conversion, ConversionFlag, cast_to_integer(MinFieldWidth), Precision, cast_to_integer(PrecisionLength), ConversionType),
|
|
|
|
+ lists:flatten(String).
|
|
|
|
|
|
%% @doc
|
|
%% @doc
|
|
%% A conversion specifier contains two or more characters and has the following components, which must occur in this order:
|
|
%% A conversion specifier contains two or more characters and has the following components, which must occur in this order:
|
|
@@ -495,140 +496,148 @@ stringformat(Input, Conversion) ->
|
|
%% 5. Precision (optional), given as a "." (dot) followed by the precision. If specified as "*" (an asterisk), the actual width is read from the next element of the tuple in values, and the value to convert comes after the precision.
|
|
%% 5. Precision (optional), given as a "." (dot) followed by the precision. If specified as "*" (an asterisk), the actual width is read from the next element of the tuple in values, and the value to convert comes after the precision.
|
|
%% 6. Length modifier (optional).
|
|
%% 6. Length modifier (optional).
|
|
%% 7. Conversion type.
|
|
%% 7. Conversion type.
|
|
-
|
|
|
|
|
|
+
|
|
stringformat_io(Input, _Conversion, _ConversionFlag, [],
|
|
stringformat_io(Input, _Conversion, _ConversionFlag, [],
|
|
- _Precision, _PrecisionLength, "s") when is_list(Input) ->
|
|
|
|
- Format = lists:flatten(io_lib:format("~~s", [])),
|
|
|
|
- io_lib:format(Format, [Input]);
|
|
|
|
|
|
+ _Precision, _PrecisionLength, "s") when is_list(Input) ->
|
|
|
|
+ Format = lists:flatten(io_lib:format("~~s", [])),
|
|
|
|
+ io_lib:format(Format, [Input]);
|
|
stringformat_io(Input, _Conversion, ConversionFlag, MinFieldWidth,
|
|
stringformat_io(Input, _Conversion, ConversionFlag, MinFieldWidth,
|
|
- _Precision, _PrecisionLength, "s") when is_list(Input) ->
|
|
|
|
- %Conversion = [ConversionFlag, MinFieldWidth, Precision, PrecisionLength, ConversionType],
|
|
|
|
- InputLength = erlang:length(Input),
|
|
|
|
- case erlang:abs(MinFieldWidth) < InputLength of
|
|
|
|
- true ->
|
|
|
|
- MFW = InputLength;
|
|
|
|
- false ->
|
|
|
|
- MFW = MinFieldWidth
|
|
|
|
- end,
|
|
|
|
- Format = lists:flatten(io_lib:format("~~~s~ps", [ConversionFlag,MFW])),
|
|
|
|
- io_lib:format(Format, [Input]);
|
|
|
|
|
|
+ _Precision, _PrecisionLength, "s") when is_list(Input) ->
|
|
|
|
+ %Conversion = [ConversionFlag, MinFieldWidth, Precision, PrecisionLength, ConversionType],
|
|
|
|
+ InputLength = erlang:length(Input),
|
|
|
|
+ case erlang:abs(MinFieldWidth) < InputLength of
|
|
|
|
+ true ->
|
|
|
|
+ MFW = InputLength;
|
|
|
|
+ false ->
|
|
|
|
+ MFW = MinFieldWidth
|
|
|
|
+ end,
|
|
|
|
+ Format = lists:flatten(io_lib:format("~~~s~ps", [ConversionFlag,MFW])),
|
|
|
|
+ io_lib:format(Format, [Input]);
|
|
stringformat_io(Input, _Conversion, _ConversionFlag, MinFieldWidth,
|
|
stringformat_io(Input, _Conversion, _ConversionFlag, MinFieldWidth,
|
|
- Precision, PrecisionLength, "f") when Precision == ".", MinFieldWidth == 0 ->
|
|
|
|
|
|
+ Precision, PrecisionLength, "f") when Precision == ".", MinFieldWidth == 0 ->
|
|
Conversion1 = lists:concat(["","",Precision,PrecisionLength,"f"]),
|
|
Conversion1 = lists:concat(["","",Precision,PrecisionLength,"f"]),
|
|
stringformat_io(Input, Conversion1, [], [], Precision, PrecisionLength, "f");
|
|
stringformat_io(Input, Conversion1, [], [], Precision, PrecisionLength, "f");
|
|
stringformat_io(Input, Conversion, ConversionFlag, MinFieldWidth,
|
|
stringformat_io(Input, Conversion, ConversionFlag, MinFieldWidth,
|
|
- Precision, "", "f") when Precision == "." ->
|
|
|
|
|
|
+ Precision, "", "f") when Precision == "." ->
|
|
Format = re:replace(Conversion, "f", "d", [{return, list}] ),
|
|
Format = re:replace(Conversion, "f", "d", [{return, list}] ),
|
|
stringformat_io(Input, Format, ConversionFlag, MinFieldWidth,
|
|
stringformat_io(Input, Format, ConversionFlag, MinFieldWidth,
|
|
- Precision, "", "d");
|
|
|
|
|
|
+ Precision, "", "d");
|
|
stringformat_io(Input, Conversion, _ConversionFlag, _MinFieldWidth,
|
|
stringformat_io(Input, Conversion, _ConversionFlag, _MinFieldWidth,
|
|
- _Precision, _PrecisionLength, "f")->
|
|
|
|
- %Conversion = [ConversionFlag, MinFieldWidth, Precision, PrecisionLength, ConversionType],
|
|
|
|
- Format = "~" ++ Conversion,
|
|
|
|
- io_lib:format(Format, [cast_to_float(Input)]);
|
|
|
|
|
|
+ _Precision, _PrecisionLength, "f")->
|
|
|
|
+ %Conversion = [ConversionFlag, MinFieldWidth, Precision, PrecisionLength, ConversionType],
|
|
|
|
+ Format = "~" ++ Conversion,
|
|
|
|
+ io_lib:format(Format, [cast_to_float(Input)]);
|
|
stringformat_io(Input, Conversion, _ConversionFlag, _MinFieldWidth,
|
|
stringformat_io(Input, Conversion, _ConversionFlag, _MinFieldWidth,
|
|
- [], [], "d")->
|
|
|
|
- %?debugMsg("plain d"),
|
|
|
|
- %Conversion = [ConversionFlag, MinFieldWidth, Precision, PrecisionLength, ConversionType],
|
|
|
|
- Format = "~" ++ re:replace(Conversion, "d", "B", [{return, list}] ),
|
|
|
|
- io_lib:format(Format, [cast_to_integer(Input)]);
|
|
|
|
|
|
+ [], [], "d")->
|
|
|
|
+ %?debugMsg("plain d"),
|
|
|
|
+ %Conversion = [ConversionFlag, MinFieldWidth, Precision, PrecisionLength, ConversionType],
|
|
|
|
+ Format = "~" ++ re:replace(Conversion, "d", "B", [{return, list}] ),
|
|
|
|
+ io_lib:format(Format, [cast_to_integer(Input)]);
|
|
stringformat_io(Input, _Conversion, "-", MinFieldWidth,
|
|
stringformat_io(Input, _Conversion, "-", MinFieldWidth,
|
|
- _Precision, PrecisionLength, "d") when MinFieldWidth > 0 ->
|
|
|
|
- %Format = "~" ++ re:replace(Conversion, "d", "B", [{return, list}] ),
|
|
|
|
- DecimalFormat = "~" ++ integer_to_list(PrecisionLength) ++ "..0B",
|
|
|
|
- Decimal = lists:flatten( io_lib:format(DecimalFormat, [cast_to_integer(Input)]) ),
|
|
|
|
- SpaceFormat = "~" ++ integer_to_list(MinFieldWidth - erlang:length(Decimal)) ++ "s",
|
|
|
|
- Spaces = io_lib:format(SpaceFormat,[""]),
|
|
|
|
- ?debugFmt("Spaces: |~s|", [Spaces]),
|
|
|
|
- ?debugFmt("Decimal: ~s", [Decimal]),
|
|
|
|
- [lists:flatten(Decimal ++ Spaces)];
|
|
|
|
|
|
+ _Precision, PrecisionLength, "d") when MinFieldWidth > 0 ->
|
|
|
|
+ %Format = "~" ++ re:replace(Conversion, "d", "B", [{return, list}] ),
|
|
|
|
+ DecimalFormat = "~" ++ integer_to_list(PrecisionLength) ++ "..0B",
|
|
|
|
+ Decimal = lists:flatten( io_lib:format(DecimalFormat, [cast_to_integer(Input)]) ),
|
|
|
|
+ SpaceFormat = "~" ++ integer_to_list(MinFieldWidth - erlang:length(Decimal)) ++ "s",
|
|
|
|
+ Spaces = io_lib:format(SpaceFormat,[""]),
|
|
|
|
+ ?debugFmt("Spaces: |~s|", [Spaces]),
|
|
|
|
+ ?debugFmt("Decimal: ~s", [Decimal]),
|
|
|
|
+ [lists:flatten(Decimal ++ Spaces)];
|
|
stringformat_io(Input, _Conversion, _ConversionFlag, MinFieldWidth,
|
|
stringformat_io(Input, _Conversion, _ConversionFlag, MinFieldWidth,
|
|
- _Precision, PrecisionLength, "d") when MinFieldWidth > 0 ->
|
|
|
|
- %Format = "~" ++ re:replace(Conversion, "d", "B", [{return, list}] ),
|
|
|
|
- DecimalFormat = "~" ++ integer_to_list(PrecisionLength) ++ "..0B",
|
|
|
|
- Decimal = lists:flatten( io_lib:format(DecimalFormat, [cast_to_integer(Input)]) ),
|
|
|
|
- SpaceFormat = "~" ++ integer_to_list(MinFieldWidth - erlang:length(Decimal)) ++ "s",
|
|
|
|
- Spaces = io_lib:format(SpaceFormat,[""]),
|
|
|
|
- ?debugFmt("Spaces: |~s|", [Spaces]),
|
|
|
|
- ?debugFmt("Decimal: ~s", [Decimal]),
|
|
|
|
- [lists:flatten(Spaces ++ Decimal)];
|
|
|
|
|
|
+ _Precision, PrecisionLength, "d") when MinFieldWidth > 0 ->
|
|
|
|
+ %Format = "~" ++ re:replace(Conversion, "d", "B", [{return, list}] ),
|
|
|
|
+ DecimalFormat = "~" ++ integer_to_list(PrecisionLength) ++ "..0B",
|
|
|
|
+ Decimal = lists:flatten( io_lib:format(DecimalFormat, [cast_to_integer(Input)]) ),
|
|
|
|
+ SpaceFormat = "~" ++ integer_to_list(MinFieldWidth - erlang:length(Decimal)) ++ "s",
|
|
|
|
+ Spaces = io_lib:format(SpaceFormat,[""]),
|
|
|
|
+ ?debugFmt("Spaces: |~s|", [Spaces]),
|
|
|
|
+ ?debugFmt("Decimal: ~s", [Decimal]),
|
|
|
|
+ [lists:flatten(Spaces ++ Decimal)];
|
|
stringformat_io(Input, _Conversion, _ConversionFlag, _MinFieldWidth,
|
|
stringformat_io(Input, _Conversion, _ConversionFlag, _MinFieldWidth,
|
|
- _Precision, PrecisionLength, "d") ->
|
|
|
|
- %Conversion = [ConversionFlag, MinFieldWidth, Precision, PrecisionLength, ConversionType],
|
|
|
|
- %Format = "~" ++ PrecisionLength ++ "..0" ++ re:replace(Conversion, "d", "B", [{return, list}] ),
|
|
|
|
- ?debugFmt("precision d, Conversion: ~p~n", [Conversion]),
|
|
|
|
- Format = lists:flatten("~" ++ io_lib:format("~B..0B",[PrecisionLength])),
|
|
|
|
- ?debugFmt("Format: ~p~n",[Format]),
|
|
|
|
- io_lib:format(Format, [cast_to_integer(Input)]);
|
|
|
|
|
|
+ _Precision, PrecisionLength, "d") ->
|
|
|
|
+ %Conversion = [ConversionFlag, MinFieldWidth, Precision, PrecisionLength, ConversionType],
|
|
|
|
+ %Format = "~" ++ PrecisionLength ++ "..0" ++ re:replace(Conversion, "d", "B", [{return, list}] ),
|
|
|
|
+ %?debugFmt("precision d, Conversion: ~p~n", [Conversion]),
|
|
|
|
+ Format = lists:flatten("~" ++ io_lib:format("~B..0B",[PrecisionLength])),
|
|
|
|
+ ?debugFmt("Format: ~p~n",[Format]),
|
|
|
|
+ io_lib:format(Format, [cast_to_integer(Input)]);
|
|
stringformat_io(Input, Conversion, _ConversionFlag, _MinFieldWidth,
|
|
stringformat_io(Input, Conversion, _ConversionFlag, _MinFieldWidth,
|
|
- _Precision, _PrecisionLength, "i")->
|
|
|
|
- Format = "~" ++ re:replace(Conversion, "i", "B", [{return, list}] ),
|
|
|
|
- io_lib:format(Format, [cast_to_integer(Input)]);
|
|
|
|
|
|
+ _Precision, _PrecisionLength, "i")->
|
|
|
|
+ Format = "~" ++ re:replace(Conversion, "i", "B", [{return, list}] ),
|
|
|
|
+ io_lib:format(Format, [cast_to_integer(Input)]);
|
|
stringformat_io(Input, Conversion, _ConversionFlag, _MinFieldWidth,
|
|
stringformat_io(Input, Conversion, _ConversionFlag, _MinFieldWidth,
|
|
- _Precision, _PrecisionLength, "X")->
|
|
|
|
- Format = "~" ++ re:replace(Conversion, "X", ".16B", [{return, list}] ),
|
|
|
|
- io_lib:format(Format, [cast_to_integer(Input)]);
|
|
|
|
|
|
+ _Precision, _PrecisionLength, "X")->
|
|
|
|
+ Format = "~" ++ re:replace(Conversion, "X", ".16B", [{return, list}] ),
|
|
|
|
+ io_lib:format(Format, [cast_to_integer(Input)]);
|
|
stringformat_io(Input, Conversion, _ConversionFlag, _MinFieldWidth,
|
|
stringformat_io(Input, Conversion, _ConversionFlag, _MinFieldWidth,
|
|
- _Precision, _PrecisionLength, "x")->
|
|
|
|
- Format = "~" ++ re:replace(Conversion, "x", ".16b", [{return, list}] ),
|
|
|
|
- io_lib:format(Format, [cast_to_integer(Input)]);
|
|
|
|
|
|
+ _Precision, _PrecisionLength, "x")->
|
|
|
|
+ Format = "~" ++ re:replace(Conversion, "x", ".16b", [{return, list}] ),
|
|
|
|
+ io_lib:format(Format, [cast_to_integer(Input)]);
|
|
stringformat_io(Input, Conversion, _ConversionFlag, _MinFieldWidth,
|
|
stringformat_io(Input, Conversion, _ConversionFlag, _MinFieldWidth,
|
|
- _Precision, _PrecisionLength, "o")->
|
|
|
|
- Format = "~" ++ re:replace(Conversion, "o", ".8b", [{return, list}] ),
|
|
|
|
- io_lib:format(Format, [cast_to_integer(Input)]);
|
|
|
|
|
|
+ _Precision, _PrecisionLength, "o")->
|
|
|
|
+ Format = "~" ++ re:replace(Conversion, "o", ".8b", [{return, list}] ),
|
|
|
|
+ io_lib:format(Format, [cast_to_integer(Input)]);
|
|
stringformat_io(Input, _Conversion, _ConversionFlag, _MinFieldWidth,
|
|
stringformat_io(Input, _Conversion, _ConversionFlag, _MinFieldWidth,
|
|
- Precision, PrecisionLength, "e") when is_integer(PrecisionLength), PrecisionLength >= 2->
|
|
|
|
- ?debugFmt("PrecisionLength ~p~n", [PrecisionLength]),
|
|
|
|
- Conversion1 = lists:concat(["","",Precision,PrecisionLength + 1,"e"]),
|
|
|
|
- Format = "~" ++ Conversion1,
|
|
|
|
- io_lib:format(Format, [cast_to_float(Input)]);
|
|
|
|
|
|
+ Precision, PrecisionLength, "e") when is_integer(PrecisionLength), PrecisionLength >= 2->
|
|
|
|
+ ?debugFmt("PrecisionLength ~p~n", [PrecisionLength]),
|
|
|
|
+ Conversion1 = lists:concat(["","",Precision,PrecisionLength + 1,"e"]),
|
|
|
|
+ Format = "~" ++ Conversion1,
|
|
|
|
+ io_lib:format(Format, [cast_to_float(Input)]);
|
|
stringformat_io(Input, Conversion, ConversionFlag, MinFieldWidth,
|
|
stringformat_io(Input, Conversion, ConversionFlag, MinFieldWidth,
|
|
- "", [], "e")->
|
|
|
|
- Format = "~" ++ re:replace(Conversion, "e", ".6e", [{return, list}] ),
|
|
|
|
- Raw = lists:flatten(stringformat_io(Input, Format, ConversionFlag, MinFieldWidth,
|
|
|
|
- ".", 6, "e")
|
|
|
|
- ),
|
|
|
|
- %io:format("Raw: ~p~n", [Raw]),
|
|
|
|
- Elocate = string:rstr(Raw,"e+"),
|
|
|
|
- %io:format("Elocate: ~p~n", [Elocate]),
|
|
|
|
- String = [string:substr(Raw,1,Elocate-1) ++ "e+"
|
|
|
|
- ++ io_lib:format("~2..0B",[list_to_integer(string:substr(Raw,Elocate+2))])], %works till +99, then outputs "**"
|
|
|
|
- %io:format("String: ~p~n", [String]),
|
|
|
|
- String;
|
|
|
|
|
|
+ "", [], "e")->
|
|
|
|
+ Format = "~" ++ re:replace(Conversion, "e", ".6e", [{return, list}] ),
|
|
|
|
+ Raw = lists:flatten(stringformat_io(Input, Format, ConversionFlag, MinFieldWidth,
|
|
|
|
+ ".", 6, "e")
|
|
|
|
+ ),
|
|
|
|
+ %io:format("Raw: ~p~n", [Raw]),
|
|
|
|
+ Elocate = string:rstr(Raw,"e+"),
|
|
|
|
+ %io:format("Elocate: ~p~n", [Elocate]),
|
|
|
|
+ String = [string:substr(Raw,1,Elocate-1) ++ "e+"
|
|
|
|
+ ++ io_lib:format("~2..0B",[list_to_integer(string:substr(Raw,Elocate+2))])], %works till +99, then outputs "**"
|
|
|
|
+ %io:format("String: ~p~n", [String]),
|
|
|
|
+ String;
|
|
stringformat_io(Input, Conversion, ConversionFlag, MinFieldWidth,
|
|
stringformat_io(Input, Conversion, ConversionFlag, MinFieldWidth,
|
|
- Precision, PrecisionLength, "E")->
|
|
|
|
- Format = re:replace(Conversion, "E", "e", [{return, list}] ),
|
|
|
|
- [Str] = stringformat_io(Input, Format, ConversionFlag, MinFieldWidth,
|
|
|
|
- Precision, PrecisionLength, "e"),
|
|
|
|
- [string:to_upper(Str)].
|
|
|
|
-
|
|
|
|
|
|
+ Precision, PrecisionLength, "E")->
|
|
|
|
+ Format = re:replace(Conversion, "E", "e", [{return, list}] ),
|
|
|
|
+ [Str] = stringformat_io(Input, Format, ConversionFlag, MinFieldWidth,
|
|
|
|
+ Precision, PrecisionLength, "e"),
|
|
|
|
+ [string:to_upper(Str)].
|
|
|
|
+
|
|
|
|
+%% @doc Strips all [X]HTML tags.
|
|
|
|
+striptags(Input) when is_binary(Input) ->
|
|
|
|
+ striptags(binary_to_list(Input));
|
|
|
|
+striptags(Input) ->
|
|
|
|
+ Regex = "(<[^>]+>)",
|
|
|
|
+ Result = re:replace(Input,Regex,"", [global,{return,list}]),
|
|
|
|
+ Result.
|
|
|
|
+
|
|
cast_to_float([]) ->
|
|
cast_to_float([]) ->
|
|
[];
|
|
[];
|
|
cast_to_float(Input) when is_float(Input) ->
|
|
cast_to_float(Input) when is_float(Input) ->
|
|
- Input;
|
|
|
|
|
|
+ Input;
|
|
cast_to_float(Input) when is_integer(Input) ->
|
|
cast_to_float(Input) when is_integer(Input) ->
|
|
- Input + 0.0;
|
|
|
|
|
|
+ Input + 0.0;
|
|
cast_to_float(Input) ->
|
|
cast_to_float(Input) ->
|
|
- try list_to_float(Input)
|
|
|
|
- catch
|
|
|
|
- error:_Reason ->
|
|
|
|
- list_to_integer(Input) + 0.0
|
|
|
|
- end.
|
|
|
|
|
|
+ try list_to_float(Input)
|
|
|
|
+ catch
|
|
|
|
+ error:_Reason ->
|
|
|
|
+ list_to_integer(Input) + 0.0
|
|
|
|
+ end.
|
|
|
|
|
|
cast_to_integer([]) ->
|
|
cast_to_integer([]) ->
|
|
[];
|
|
[];
|
|
cast_to_integer(Input) when is_integer(Input) ->
|
|
cast_to_integer(Input) when is_integer(Input) ->
|
|
- Input;
|
|
|
|
|
|
+ Input;
|
|
cast_to_integer(Input) when is_float(Input) ->
|
|
cast_to_integer(Input) when is_float(Input) ->
|
|
- erlang:round(Input);
|
|
|
|
|
|
+ erlang:round(Input);
|
|
cast_to_integer(Input) when is_list(Input)->
|
|
cast_to_integer(Input) when is_list(Input)->
|
|
- case lists:member($., Input) of
|
|
|
|
- true ->
|
|
|
|
- erlang:round(erlang:list_to_float(Input));
|
|
|
|
- false ->
|
|
|
|
- erlang:list_to_integer(Input)
|
|
|
|
- end.
|
|
|
|
-
|
|
|
|
|
|
+ case lists:member($., Input) of
|
|
|
|
+ true ->
|
|
|
|
+ erlang:round(erlang:list_to_float(Input));
|
|
|
|
+ false ->
|
|
|
|
+ erlang:list_to_integer(Input)
|
|
|
|
+ end.
|
|
|
|
+
|
|
%% @doc Converts to lowercase, removes non-word characters (alphanumerics and underscores) and converts spaces to hyphens.
|
|
%% @doc Converts to lowercase, removes non-word characters (alphanumerics and underscores) and converts spaces to hyphens.
|
|
slugify(Input) when is_binary(Input) ->
|
|
slugify(Input) when is_binary(Input) ->
|
|
slugify(binary_to_list(Input));
|
|
slugify(binary_to_list(Input));
|
|
@@ -636,16 +645,57 @@ slugify(Input) when is_list(Input) ->
|
|
slugify(Input, []).
|
|
slugify(Input, []).
|
|
|
|
|
|
%% @doc Formats a time according to the given format.
|
|
%% @doc Formats a time according to the given format.
|
|
-time(Input, "") ->
|
|
|
|
- date(Input, "f a");
|
|
|
|
|
|
+time(Input) ->
|
|
|
|
+ date(Input, "f a").
|
|
|
|
+
|
|
time(Input, FormatStr) ->
|
|
time(Input, FormatStr) ->
|
|
date(Input, FormatStr).
|
|
date(Input, FormatStr).
|
|
-
|
|
|
|
|
|
+
|
|
|
|
+timesince(Date) ->
|
|
|
|
+ timesince(Date, calendar:local_time()).
|
|
|
|
+%%algorithm taken from django code
|
|
|
|
+timesince(Date,Comparison) ->
|
|
|
|
+ Since = calendar:datetime_to_gregorian_seconds(Comparison) - calendar:datetime_to_gregorian_seconds(Date),
|
|
|
|
+ timesince0(Since, [], 0).
|
|
|
|
+
|
|
|
|
+timesince0(_, Acc, 2) ->
|
|
|
|
+ string:join(lists:reverse(Acc), ", ");
|
|
|
|
+timesince0(Seconds, Acc, Terms) when Seconds >= ?SECONDS_PER_YEAR ->
|
|
|
|
+ Years = Seconds div ?SECONDS_PER_YEAR,
|
|
|
|
+ timesince0(Seconds rem ?SECONDS_PER_YEAR, [io_lib:format("~B ~s~s", [Years, "year", pluralize(Years)])|Acc], Terms+1);
|
|
|
|
+timesince0(Seconds, Acc, Terms) when Seconds >= ?SECONDS_PER_MONTH ->
|
|
|
|
+ Months = Seconds div ?SECONDS_PER_MONTH,
|
|
|
|
+ timesince0(Seconds rem ?SECONDS_PER_MONTH, [io_lib:format("~B ~s~s", [Months, "month", pluralize(Months)])|Acc], Terms+1);
|
|
|
|
+timesince0(Seconds, Acc, Terms) when Seconds >= ?SECONDS_PER_WEEK ->
|
|
|
|
+ Weeks = Seconds div ?SECONDS_PER_WEEK,
|
|
|
|
+ timesince0(Seconds rem ?SECONDS_PER_WEEK, [io_lib:format("~B ~s~s", [Weeks, "week", pluralize(Weeks)])|Acc], Terms+1);
|
|
|
|
+timesince0(Seconds, Acc, Terms) when Seconds >= ?SECONDS_PER_DAY ->
|
|
|
|
+ Days = Seconds div ?SECONDS_PER_DAY,
|
|
|
|
+ timesince0(Seconds rem ?SECONDS_PER_DAY, [io_lib:format("~B ~s~s", [Days, "day", pluralize(Days)])|Acc], Terms+1);
|
|
|
|
+timesince0(Seconds, Acc, Terms) when Seconds >= ?SECONDS_PER_HOUR ->
|
|
|
|
+ Hours = Seconds div ?SECONDS_PER_HOUR,
|
|
|
|
+ timesince0(Seconds rem ?SECONDS_PER_HOUR, [io_lib:format("~B ~s~s", [Hours, "hour", pluralize(Hours)])|Acc], Terms+1);
|
|
|
|
+timesince0(Seconds, Acc, Terms) when Seconds >= ?SECONDS_PER_MINUTE ->
|
|
|
|
+ Minutes = Seconds div ?SECONDS_PER_MINUTE,
|
|
|
|
+ timesince0(Seconds rem ?SECONDS_PER_MINUTE,[io_lib:format("~B ~s~s", [Minutes, "minute", pluralize(Minutes)])|Acc], Terms+1);
|
|
|
|
+timesince0(Seconds, Acc, Terms) when Seconds >= 1 ->
|
|
|
|
+ timesince0(0, [io_lib:format("~B ~s~s", [Seconds, "second", pluralize(Seconds)])|Acc], Terms+1);
|
|
|
|
+timesince0(Seconds, [], 0) when Seconds =< 0 ->
|
|
|
|
+ timesince0(0, ["0 minutes"], 1);
|
|
|
|
+timesince0(0, Acc, Terms) ->
|
|
|
|
+ timesince0(0, Acc, Terms+1).
|
|
|
|
+
|
|
|
|
+timeuntil(Date) ->
|
|
|
|
+ timesince(calendar:local_time(),Date).
|
|
|
|
+
|
|
|
|
+timeuntil(Date,Comparison) ->
|
|
|
|
+ timesince(Comparison,Date).
|
|
|
|
+
|
|
%% @doc Converts a string into titlecase.
|
|
%% @doc Converts a string into titlecase.
|
|
title(Input) when is_binary(Input) ->
|
|
title(Input) when is_binary(Input) ->
|
|
title(binary_to_list(Input));
|
|
title(binary_to_list(Input));
|
|
title(Input) when is_list(Input) ->
|
|
title(Input) when is_list(Input) ->
|
|
- title(Input, [], capnext).
|
|
|
|
|
|
+ title(Input, []).
|
|
|
|
|
|
%% @doc Truncates a string after a certain number of words.
|
|
%% @doc Truncates a string after a certain number of words.
|
|
truncatewords(Input, Max) when is_binary(Input) ->
|
|
truncatewords(Input, Max) when is_binary(Input) ->
|
|
@@ -655,6 +705,28 @@ truncatewords(_Input, Max) when Max =< 0 ->
|
|
truncatewords(Input, Max) ->
|
|
truncatewords(Input, Max) ->
|
|
truncatewords(Input, Max, []).
|
|
truncatewords(Input, Max, []).
|
|
|
|
|
|
|
|
+%% @doc Recursively takes a self-nested list and returns an HTML unordered list -- WITHOUT opening and closing <ul> tags.
|
|
|
|
+%%TODO: finish unordered_list
|
|
|
|
+%% unordered_list(List) ->
|
|
|
|
+%% lists:reverse(unordered_list(List, [])).
|
|
|
|
+%%
|
|
|
|
+%% unordered_list([], Acc) ->
|
|
|
|
+%% Acc;
|
|
|
|
+%% unordered_list(List, Acc) ->
|
|
|
|
+%% [First|Rest] = List,
|
|
|
|
+%% io:format("First is_list: ~p, ~p~n", [First, is_list(First)]),
|
|
|
|
+%% case is_list(First) of
|
|
|
|
+%% true ->
|
|
|
|
+%% [First|Rest] = First,
|
|
|
|
+%% Return = [First | Acc],
|
|
|
|
+%% "<ul>" ++ unordered_list(Rest,Return) + "</ul>";
|
|
|
|
+%% false ->
|
|
|
|
+%% Return = [First | Acc],
|
|
|
|
+%% "<li>" ++ unordered_list(Rest,Return) + "</li>"
|
|
|
|
+%% end.
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
%% @doc Converts a string into all uppercase.
|
|
%% @doc Converts a string into all uppercase.
|
|
upper(Input) when is_binary(Input) ->
|
|
upper(Input) when is_binary(Input) ->
|
|
list_to_binary(upper(binary_to_list(Input)));
|
|
list_to_binary(upper(binary_to_list(Input)));
|
|
@@ -675,22 +747,22 @@ wordcount(Input) when is_list(Input) ->
|
|
|
|
|
|
%% @doc Wraps words at specified line length, uses <BR/> html tag to delimit lines
|
|
%% @doc Wraps words at specified line length, uses <BR/> html tag to delimit lines
|
|
wordwrap(Input, Number) when is_binary(Input) ->
|
|
wordwrap(Input, Number) when is_binary(Input) ->
|
|
- wordwrap_io(binary_to_list(Input), Number);
|
|
|
|
|
|
+ wordwrap(binary_to_list(Input), Number);
|
|
wordwrap(Input, Number) when is_list(Input) ->
|
|
wordwrap(Input, Number) when is_list(Input) ->
|
|
- wordwrap_io(Input, Number).
|
|
|
|
-
|
|
|
|
|
|
+ wordwrap(Input, [], [], 0, Number).
|
|
|
|
+
|
|
%% @doc Given a string mapping values for true, false and (optionally) undefined, returns one of those strings according to the value.
|
|
%% @doc Given a string mapping values for true, false and (optionally) undefined, returns one of those strings according to the value.
|
|
yesno(Bool, Choices) when is_binary(Choices) ->
|
|
yesno(Bool, Choices) when is_binary(Choices) ->
|
|
- yesno_io(binary_to_list(Bool), Choices);
|
|
|
|
|
|
+ yesno_io(binary_to_list(Bool), Choices);
|
|
yesno(Bool, Choices) when is_list(Choices) ->
|
|
yesno(Bool, Choices) when is_list(Choices) ->
|
|
- yesno_io(Bool, Choices).
|
|
|
|
|
|
+ yesno_io(Bool, Choices).
|
|
|
|
|
|
% internal
|
|
% internal
|
|
|
|
|
|
addslashes([], Acc) ->
|
|
addslashes([], Acc) ->
|
|
lists:reverse(Acc);
|
|
lists:reverse(Acc);
|
|
-addslashes([H|T], Acc) when H =:= $"; H =:= $' ->
|
|
|
|
- addslashes(T, [H, $\\|Acc]);
|
|
|
|
|
|
+addslashes([H|T], Acc) when H =:= $"; H =:= $' ->
|
|
|
|
+addslashes(T, [H, $\\|Acc]);
|
|
addslashes([H|T], Acc) ->
|
|
addslashes([H|T], Acc) ->
|
|
addslashes(T, [H|Acc]).
|
|
addslashes(T, [H|Acc]).
|
|
|
|
|
|
@@ -737,9 +809,9 @@ escape([C | Rest], Acc) ->
|
|
escapejs([], Acc) ->
|
|
escapejs([], Acc) ->
|
|
lists:reverse(Acc);
|
|
lists:reverse(Acc);
|
|
escapejs([C | Rest], Acc) when C < 32; C =:= $"; C =:= $'; C =:= $\\; C =:= $<;
|
|
escapejs([C | Rest], Acc) when C < 32; C =:= $"; C =:= $'; C =:= $\\; C =:= $<;
|
|
- C =:= $>; C =:= $&; C =:= $=; C =:= $-; C =:= $;;
|
|
|
|
- C =:= 8232; C =:= 8233 -> % just following django here...
|
|
|
|
- escapejs(Rest, lists:reverse(lists:flatten(io_lib:format("\\u~4.16.0B", [C])), Acc));
|
|
|
|
|
|
+C =:= $>; C =:= $&; C =:= $=; C =:= $-; C =:= $;;
|
|
|
|
+C =:= 8232; C =:= 8233 -> % just following django here...
|
|
|
|
+escapejs(Rest, lists:reverse(lists:flatten(io_lib:format("\\u~4.16.0B", [C])), Acc));
|
|
escapejs([C | Rest], Acc) ->
|
|
escapejs([C | Rest], Acc) ->
|
|
escapejs(Rest, [C | Acc]).
|
|
escapejs(Rest, [C | Acc]).
|
|
|
|
|
|
@@ -800,26 +872,26 @@ lower(Input, Index) ->
|
|
phone2numeric([], Acc) ->
|
|
phone2numeric([], Acc) ->
|
|
lists:reverse(Acc);
|
|
lists:reverse(Acc);
|
|
phone2numeric([H|T], Acc) when H >= $a, H =< $c; H >= $A, H =< $C ->
|
|
phone2numeric([H|T], Acc) when H >= $a, H =< $c; H >= $A, H =< $C ->
|
|
- phone2numeric(T, [$2|Acc]);
|
|
|
|
|
|
+phone2numeric(T, [$2|Acc]);
|
|
phone2numeric([H|T], Acc) when H >= $d, H =< $f; H >= $D, H =< $F ->
|
|
phone2numeric([H|T], Acc) when H >= $d, H =< $f; H >= $D, H =< $F ->
|
|
- phone2numeric(T, [$3|Acc]);
|
|
|
|
|
|
+phone2numeric(T, [$3|Acc]);
|
|
phone2numeric([H|T], Acc) when H >= $g, H =< $i; H >= $G, H =< $I ->
|
|
phone2numeric([H|T], Acc) when H >= $g, H =< $i; H >= $G, H =< $I ->
|
|
- phone2numeric(T, [$4|Acc]);
|
|
|
|
|
|
+phone2numeric(T, [$4|Acc]);
|
|
phone2numeric([H|T], Acc) when H >= $j, H =< $l; H >= $J, H =< $L ->
|
|
phone2numeric([H|T], Acc) when H >= $j, H =< $l; H >= $J, H =< $L ->
|
|
- phone2numeric(T, [$5|Acc]);
|
|
|
|
|
|
+phone2numeric(T, [$5|Acc]);
|
|
phone2numeric([H|T], Acc) when H >= $m, H =< $o; H >= $M, H =< $O ->
|
|
phone2numeric([H|T], Acc) when H >= $m, H =< $o; H >= $M, H =< $O ->
|
|
- phone2numeric(T, [$6|Acc]);
|
|
|
|
|
|
+phone2numeric(T, [$6|Acc]);
|
|
phone2numeric([H|T], Acc) when H >= $p, H =< $s; H >= $P, H =< $S ->
|
|
phone2numeric([H|T], Acc) when H >= $p, H =< $s; H >= $P, H =< $S ->
|
|
- phone2numeric(T, [$7|Acc]);
|
|
|
|
|
|
+phone2numeric(T, [$7|Acc]);
|
|
phone2numeric([H|T], Acc) when H >= $t, H =< $v; H >= $T, H =< $V ->
|
|
phone2numeric([H|T], Acc) when H >= $t, H =< $v; H >= $T, H =< $V ->
|
|
- phone2numeric(T, [$8|Acc]);
|
|
|
|
|
|
+phone2numeric(T, [$8|Acc]);
|
|
phone2numeric([H|T], Acc) when H >= $w, H =< $z; H >= $W, H =< $Z ->
|
|
phone2numeric([H|T], Acc) when H >= $w, H =< $z; H >= $W, H =< $Z ->
|
|
- phone2numeric(T, [$9|Acc]);
|
|
|
|
|
|
+phone2numeric(T, [$9|Acc]);
|
|
phone2numeric([H|T], Acc) ->
|
|
phone2numeric([H|T], Acc) ->
|
|
phone2numeric(T, [H|Acc]).
|
|
phone2numeric(T, [H|Acc]).
|
|
|
|
|
|
-
|
|
|
|
-
|
|
|
|
|
|
+
|
|
|
|
+
|
|
slugify([], Acc) ->
|
|
slugify([], Acc) ->
|
|
lists:reverse(Acc);
|
|
lists:reverse(Acc);
|
|
slugify([H|T], Acc) when H >= $A, H =< $Z ->
|
|
slugify([H|T], Acc) when H >= $A, H =< $Z ->
|
|
@@ -827,22 +899,18 @@ slugify([H|T], Acc) when H >= $A, H =< $Z ->
|
|
slugify([$\ |T], Acc) ->
|
|
slugify([$\ |T], Acc) ->
|
|
slugify(T, [$-|Acc]);
|
|
slugify(T, [$-|Acc]);
|
|
slugify([H|T], Acc) when H >= $a, H =< $z; H >= $0, H =< $9; H =:= $_ ->
|
|
slugify([H|T], Acc) when H >= $a, H =< $z; H >= $0, H =< $9; H =:= $_ ->
|
|
- slugify(T, [H|Acc]);
|
|
|
|
|
|
+slugify(T, [H|Acc]);
|
|
slugify([_|T], Acc) ->
|
|
slugify([_|T], Acc) ->
|
|
slugify(T, Acc).
|
|
slugify(T, Acc).
|
|
|
|
|
|
-title([], Acc, _) ->
|
|
|
|
|
|
+title([], Acc) ->
|
|
lists:reverse(Acc);
|
|
lists:reverse(Acc);
|
|
-title([$\ = H|T], Acc, capnext) ->
|
|
|
|
- title(T, [H|Acc], capnext);
|
|
|
|
-title([H|T], Acc, capnext) when H >= $a, H =< $z ->
|
|
|
|
- title(T, [H - $a + $A|Acc], dont);
|
|
|
|
-title([H|T], Acc, capnext) ->
|
|
|
|
- title(T, [H|Acc], dont);
|
|
|
|
-title([$\ = H|T], Acc, dont) ->
|
|
|
|
- title(T, [H|Acc], capnext);
|
|
|
|
-title([H|T], Acc, dont) ->
|
|
|
|
- title(T, [H|Acc], dont).
|
|
|
|
|
|
+title([Char | Rest], [] = Acc) when Char >= $a, Char =< $z ->
|
|
|
|
+ title(Rest, [Char + ($A - $a) | Acc]);
|
|
|
|
+title([Char | Rest], [$\ |_] = Acc) when Char >= $a, Char =< $z ->
|
|
|
|
+ title(Rest, [Char + ($A - $a) | Acc]);
|
|
|
|
+title([Char | Rest], Acc) ->
|
|
|
|
+ title(Rest, [Char | Acc]).
|
|
|
|
|
|
truncatewords([], _WordsLeft, Acc) ->
|
|
truncatewords([], _WordsLeft, Acc) ->
|
|
lists:reverse(Acc);
|
|
lists:reverse(Acc);
|
|
@@ -862,28 +930,26 @@ wordcount([C1, C2|Rest], Count) when C1 =/= $\ andalso C2 =:= $\ ->
|
|
wordcount([_|Rest], Count) ->
|
|
wordcount([_|Rest], Count) ->
|
|
wordcount(Rest, Count).
|
|
wordcount(Rest, Count).
|
|
|
|
|
|
-% based on: http://pragdave.pragprog.com/pragdave/2007/04/testfirst_word_.html
|
|
|
|
-% This is the exported function: it passes the initial
|
|
|
|
-% result set to the internal versions
|
|
|
|
-wordwrap_io(Input, Number) ->
|
|
|
|
- Words = string:tokens(Input, " "),
|
|
|
|
- string:join(lists:reverse(wordwrap_io(Words, [""], Number)),"").
|
|
|
|
-% When we run out of words, we're done
|
|
|
|
-wordwrap_io([], Result, _Number) ->
|
|
|
|
- Result;
|
|
|
|
-% Adding a word to an empty line
|
|
|
|
-wordwrap_io([ NextWord | Rest ], [ "" | PreviousLines ], Number) ->
|
|
|
|
- wordwrap_io(Rest, [ NextWord | PreviousLines ], Number);
|
|
|
|
-% Or to a line that's already partially full. There are two cases:
|
|
|
|
-% 1. The word fits
|
|
|
|
-wordwrap_io([ NextWord | Rest ], [ CurrentLine | PreviousLines ], Number)
|
|
|
|
- when erlang:length(NextWord) + erlang:length(CurrentLine) < Number ->
|
|
|
|
- %wordwrap_io(Rest, [ NextWord, " ", CurrentLine | PreviousLines ], Number);
|
|
|
|
- wordwrap_io(Rest, [ lists:flatten([CurrentLine," " ,NextWord]) | PreviousLines ], Number);
|
|
|
|
-% 2. The word doesn't fit, so we create a new line
|
|
|
|
-wordwrap_io([ NextWord | Rest], [ CurrentLine | PreviousLines ], Number) ->
|
|
|
|
- wordwrap_io(Rest, [ NextWord, "\n", CurrentLine | PreviousLines ], Number).
|
|
|
|
-
|
|
|
|
|
|
+% No more input, we're done
|
|
|
|
+wordwrap([], Acc, WordAcc, _LineLength, _WrapAt) ->
|
|
|
|
+ lists:reverse(WordAcc ++ Acc);
|
|
|
|
+% Premature newline
|
|
|
|
+wordwrap([$\n | Rest], Acc, WordAcc, _LineLength, WrapAt) ->
|
|
|
|
+ wordwrap(Rest, [$\n | WordAcc ++ Acc], [], 0, WrapAt);
|
|
|
|
+% Hit the wrap length at a space character. Add a newline
|
|
|
|
+wordwrap([$\ | Rest], Acc, WordAcc, WrapAt, WrapAt) ->
|
|
|
|
+ wordwrap(Rest, [$\n | WordAcc ++ Acc], [], 0, WrapAt);
|
|
|
|
+% Hit a space character before the wrap length. Keep going
|
|
|
|
+wordwrap([$\ | Rest], Acc, WordAcc, LineLength, WrapAt) ->
|
|
|
|
+ wordwrap(Rest, [$\ | WordAcc ++ Acc], [], LineLength + 1 + erlang:length(WordAcc), WrapAt);
|
|
|
|
+% Overflowed the current line while building a word
|
|
|
|
+wordwrap([C | Rest], Acc, WordAcc, 0, WrapAt) when erlang:length(WordAcc) > WrapAt ->
|
|
|
|
+ wordwrap(Rest, Acc, [C | WordAcc], 0, WrapAt);
|
|
|
|
+wordwrap([C | Rest], Acc, WordAcc, LineLength, WrapAt) when erlang:length(WordAcc) + LineLength > WrapAt ->
|
|
|
|
+ wordwrap(Rest, [$\n | Acc], [C | WordAcc], 0, WrapAt);
|
|
|
|
+% Just building a word...
|
|
|
|
+wordwrap([C | Rest], Acc, WordAcc, LineLength, WrapAt) ->
|
|
|
|
+ wordwrap(Rest, Acc, [C | WordAcc], LineLength, WrapAt).
|
|
|
|
|
|
% Taken from quote_plus of mochiweb_util
|
|
% Taken from quote_plus of mochiweb_util
|
|
|
|
|
|
@@ -911,6 +977,46 @@ urlencode([C | Rest], Acc) ->
|
|
<<Hi:4, Lo:4>> = <<C>>,
|
|
<<Hi:4, Lo:4>> = <<C>>,
|
|
urlencode(Rest, [hexdigit(Lo), hexdigit(Hi), $\% | Acc]).
|
|
urlencode(Rest, [hexdigit(Lo), hexdigit(Hi), $\% | Acc]).
|
|
|
|
|
|
|
|
+%% @doc Converts URLs in text into clickable links.
|
|
|
|
+%%TODO: Autoescape not yet implemented
|
|
|
|
+urlize(Input) when is_binary(Input) ->
|
|
|
|
+ urlize(binary_to_list(Input),0);
|
|
|
|
+urlize(Input) ->
|
|
|
|
+ urlize(Input,0).
|
|
|
|
+
|
|
|
|
+urlize(Input, Trunc) when is_binary(Input) ->
|
|
|
|
+ urlize(binary_to_list(Input),Trunc);
|
|
|
|
+urlize(Input, Trunc) ->
|
|
|
|
+ {ok,RE} = re:compile("(([[:alpha:]]+://|www\.)[^<>[:space:]]+[[:alnum:]/])"),
|
|
|
|
+ {match,Matches} = re:run(Input,RE,[global]),
|
|
|
|
+ Indexes = lists:map(fun(Match) -> lists:nth(2,Match) end, Matches),
|
|
|
|
+ Domains = lists:map(fun({Start, Length}) -> lists:sublist(Input, Start+1, Length) end, Indexes),
|
|
|
|
+ URIDomains = lists:map(fun(Domain) -> addDefaultURI(Domain) end, Domains),
|
|
|
|
+ case Trunc == 0 of
|
|
|
|
+ true ->
|
|
|
|
+ DomainsTrunc = Domains;
|
|
|
|
+ false ->
|
|
|
|
+ DomainsTrunc = lists:map(fun(Domain) -> string:concat( string:substr(Domain,1,Trunc-3), "...") end, Domains)
|
|
|
|
+ end,
|
|
|
|
+ ReplaceList = lists:zip(URIDomains,DomainsTrunc),
|
|
|
|
+ ReplaceStrings = lists:map(fun({URIDomain,Domain}) -> lists:flatten(io_lib:format("<a href=\"~s\" rel=\"nofollow\">~s</a>",[URIDomain,Domain])) end, ReplaceList),
|
|
|
|
+ Template = re:replace(Input,"(([[:alpha:]]+://|www\.)[^<>[:space:]]+[[:alnum:]/])", "~s", [global,{return,list}]),
|
|
|
|
+ Result = lists:flatten(io_lib:format(Template,ReplaceStrings)),
|
|
|
|
+ Result.
|
|
|
|
+
|
|
|
|
+%% @doc Converts URLs into clickable links just like urlize, but truncates URLs longer than the given character limit.
|
|
|
|
+urlizetrunc(Input, Trunc) ->
|
|
|
|
+ urlize(Input, Trunc).
|
|
|
|
+
|
|
|
|
+addDefaultURI(Domain) ->
|
|
|
|
+ case string:str(Domain,"://") of
|
|
|
|
+ 0 ->
|
|
|
|
+ Domain1 = string:concat("http://",Domain);
|
|
|
|
+ _ ->
|
|
|
|
+ Domain1 = Domain
|
|
|
|
+ end,
|
|
|
|
+ Domain1.
|
|
|
|
+
|
|
hexdigit(C) when C < 10 -> $0 + C;
|
|
hexdigit(C) when C < 10 -> $0 + C;
|
|
hexdigit(C) when C < 16 -> $A + (C - 10).
|
|
hexdigit(C) when C < 16 -> $A + (C - 10).
|
|
|
|
|
|
@@ -921,69 +1027,69 @@ process_binary_match(Pre, Insertion, SizePost, Post) ->
|
|
{_, 0} -> [Pre, Insertion];
|
|
{_, 0} -> [Pre, Insertion];
|
|
_ -> [Pre, Insertion, Post]
|
|
_ -> [Pre, Insertion, Post]
|
|
end.
|
|
end.
|
|
-
|
|
|
|
|
|
+
|
|
yesno_io(Bool, Choices) ->
|
|
yesno_io(Bool, Choices) ->
|
|
-%% io:format("Bool, Choices: ~p, ~p ~n",[Bool, Choices]),
|
|
|
|
- Terms = string:tokens(Choices, ","),
|
|
|
|
- case Bool of
|
|
|
|
- true ->
|
|
|
|
- lists:nth(1, Terms);
|
|
|
|
- false ->
|
|
|
|
- lists:nth(2, Terms);
|
|
|
|
- undefined when erlang:length(Terms) == 2 -> % (converts undefined to false if no mapping for undefined is given)
|
|
|
|
- lists:nth(2, Terms);
|
|
|
|
- undefined when erlang:length(Terms) == 3 ->
|
|
|
|
- lists:nth(3, Terms);
|
|
|
|
- _ ->
|
|
|
|
- error
|
|
|
|
- end.
|
|
|
|
|
|
+ %% io:format("Bool, Choices: ~p, ~p ~n",[Bool, Choices]),
|
|
|
|
+ Terms = string:tokens(Choices, ","),
|
|
|
|
+ case Bool of
|
|
|
|
+ true ->
|
|
|
|
+ lists:nth(1, Terms);
|
|
|
|
+ false ->
|
|
|
|
+ lists:nth(2, Terms);
|
|
|
|
+ undefined when erlang:length(Terms) == 2 -> % (converts undefined to false if no mapping for undefined is given)
|
|
|
|
+ lists:nth(2, Terms);
|
|
|
|
+ undefined when erlang:length(Terms) == 3 ->
|
|
|
|
+ lists:nth(3, Terms);
|
|
|
|
+ _ ->
|
|
|
|
+ error
|
|
|
|
+ end.
|
|
|
|
|
|
%% unjoin == split in other languages; inverse of join
|
|
%% unjoin == split in other languages; inverse of join
|
|
-%% from http://www.erlang.org/pipermail/erlang-questions/2008-October/038896.html
|
|
|
|
|
|
+%%FROM: http://www.erlang.org/pipermail/erlang-questions/2008-October/038896.html
|
|
unjoin(String, []) ->
|
|
unjoin(String, []) ->
|
|
- unjoin0(String);
|
|
|
|
|
|
+ unjoin0(String);
|
|
unjoin(String, [Sep]) when is_integer(Sep) ->
|
|
unjoin(String, [Sep]) when is_integer(Sep) ->
|
|
- unjoin1(String, Sep);
|
|
|
|
|
|
+ unjoin1(String, Sep);
|
|
unjoin(String, [C1,C2|L]) when is_integer(C1), is_integer(C2) ->
|
|
unjoin(String, [C1,C2|L]) when is_integer(C1), is_integer(C2) ->
|
|
- unjoin2(String, C1, C2, L).
|
|
|
|
|
|
+ unjoin2(String, C1, C2, L).
|
|
|
|
|
|
%% Split a string at "", which is deemed to occur _between_
|
|
%% Split a string at "", which is deemed to occur _between_
|
|
%% adjacent characters, but queerly, not at the beginning
|
|
%% adjacent characters, but queerly, not at the beginning
|
|
%% or the end.
|
|
%% or the end.
|
|
|
|
|
|
unjoin0([C|Cs]) ->
|
|
unjoin0([C|Cs]) ->
|
|
- [[C] | unjoin0(Cs)];
|
|
|
|
|
|
+ [[C] | unjoin0(Cs)];
|
|
unjoin0([]) ->
|
|
unjoin0([]) ->
|
|
- [].
|
|
|
|
|
|
+ [].
|
|
|
|
|
|
%% Split a string at a single character separator.
|
|
%% Split a string at a single character separator.
|
|
|
|
|
|
unjoin1(String, Sep) ->
|
|
unjoin1(String, Sep) ->
|
|
- unjoin1_loop(String, Sep, "").
|
|
|
|
|
|
+ unjoin1_loop(String, Sep, "").
|
|
|
|
|
|
unjoin1_loop([Sep|String], Sep, Rev) ->
|
|
unjoin1_loop([Sep|String], Sep, Rev) ->
|
|
- [lists:reverse(Rev) | unjoin1(String, Sep)];
|
|
|
|
|
|
+ [lists:reverse(Rev) | unjoin1(String, Sep)];
|
|
unjoin1_loop([Chr|String], Sep, Rev) ->
|
|
unjoin1_loop([Chr|String], Sep, Rev) ->
|
|
- unjoin1_loop(String, Sep, [Chr|Rev]);
|
|
|
|
|
|
+ unjoin1_loop(String, Sep, [Chr|Rev]);
|
|
unjoin1_loop([], _, Rev) ->
|
|
unjoin1_loop([], _, Rev) ->
|
|
- [lists:reverse(Rev)].
|
|
|
|
|
|
+ [lists:reverse(Rev)].
|
|
|
|
|
|
%% Split a string at a multi-character separator
|
|
%% Split a string at a multi-character separator
|
|
%% [C1,C2|L]. These components are split out for
|
|
%% [C1,C2|L]. These components are split out for
|
|
%% a fast match.
|
|
%% a fast match.
|
|
|
|
|
|
unjoin2(String, C1, C2, L) ->
|
|
unjoin2(String, C1, C2, L) ->
|
|
- unjoin2_loop(String, C1, C2, L, "").
|
|
|
|
|
|
+ unjoin2_loop(String, C1, C2, L, "").
|
|
|
|
|
|
unjoin2_loop([C1|S = [C2|String]], C1, C2, L, Rev) ->
|
|
unjoin2_loop([C1|S = [C2|String]], C1, C2, L, Rev) ->
|
|
- case unjoin_prefix(L, String)
|
|
|
|
- of no -> unjoin2_loop(S, C1, C2, L, [C1|Rev])
|
|
|
|
- ; Rest -> [lists:reverse(Rev) | unjoin2(Rest, C1, C2, L)]
|
|
|
|
- end;
|
|
|
|
|
|
+ case unjoin_prefix(L, String)
|
|
|
|
+ of no -> unjoin2_loop(S, C1, C2, L, [C1|Rev])
|
|
|
|
+ ; Rest -> [lists:reverse(Rev) | unjoin2(Rest, C1, C2, L)]
|
|
|
|
+ end;
|
|
unjoin2_loop([Chr|String], C1, C2, L, Rev) ->
|
|
unjoin2_loop([Chr|String], C1, C2, L, Rev) ->
|
|
- unjoin2_loop(String, C1, C2, L, [Chr|Rev]);
|
|
|
|
|
|
+ unjoin2_loop(String, C1, C2, L, [Chr|Rev]);
|
|
unjoin2_loop([], _, _, _, Rev) ->
|
|
unjoin2_loop([], _, _, _, Rev) ->
|
|
- [lists:reverse(Rev)].
|
|
|
|
|
|
+ [lists:reverse(Rev)].
|
|
|
|
|
|
unjoin_prefix([C|L], [C|S]) -> unjoin_prefix(L, S);
|
|
unjoin_prefix([C|L], [C|S]) -> unjoin_prefix(L, S);
|
|
unjoin_prefix([], S) -> S;
|
|
unjoin_prefix([], S) -> S;
|