aboutsummaryrefslogtreecommitdiffstats
path: root/lib/edoc/src/edoc_lib.erl
diff options
context:
space:
mode:
Diffstat (limited to 'lib/edoc/src/edoc_lib.erl')
-rw-r--r--lib/edoc/src/edoc_lib.erl98
1 files changed, 61 insertions, 37 deletions
diff --git a/lib/edoc/src/edoc_lib.erl b/lib/edoc/src/edoc_lib.erl
index 90fb8a679c..276f48453e 100644
--- a/lib/edoc/src/edoc_lib.erl
+++ b/lib/edoc/src/edoc_lib.erl
@@ -1,3 +1,4 @@
+%% -*- coding: utf-8 -*-
%% =====================================================================
%% This library is free software; you can redistribute it and/or modify
%% it under the terms of the GNU Lesser General Public License as
@@ -30,10 +31,10 @@
parse_contact/2, escape_uri/1, join_uri/2, is_relative_uri/1,
is_name/1, to_label/1, find_doc_dirs/0, find_sources/2,
find_sources/3, find_file/3, try_subdir/2, unique/1,
- write_file/3, write_file/4, write_info_file/4,
+ write_file/3, write_file/4, write_file/5, write_info_file/4,
read_info_file/1, get_doc_env/1, get_doc_env/4, copy_file/2,
uri_get/1, run_doclet/2, run_layout/2,
- simplify_path/1, timestr/1, datestr/1]).
+ simplify_path/1, timestr/1, datestr/1, read_encoding/2]).
-import(edoc_report, [report/2, warning/2]).
@@ -57,6 +58,13 @@ datestr({Y,M,D}) ->
lists:flatten(io_lib:fwrite("~s ~w ~w",[lists:nth(M, Ms),D,Y])).
%% @private
+read_encoding(File, Options) ->
+ case epp:read_encoding(File, Options) of
+ none -> epp:default_encoding();
+ Encoding -> Encoding
+ end.
+
+%% @private
count(X, Xs) ->
count(X, Xs, 0).
@@ -228,13 +236,13 @@ end_of_sentence_1(_, false, _) ->
%% 173 - 176 { - ~ punctuation
%% 177 DEL control
%% 200 - 237 control
-%% 240 - 277 NBSP - � punctuation
-%% 300 - 326 � - � uppercase
-%% 327 � punctuation
-%% 330 - 336 � - � uppercase
-%% 337 - 366 � - � lowercase
-%% 367 � punctuation
-%% 370 - 377 � - � lowercase
+%% 240 - 277 NBSP - ¿ punctuation
+%% 300 - 326 À - Ö uppercase
+%% 327 × punctuation
+%% 330 - 336 Ø - Þ uppercase
+%% 337 - 366 ß - ö lowercase
+%% 367 ÷ punctuation
+%% 370 - 377 ø - ÿ lowercase
%% Names must begin with a lowercase letter and contain only
%% alphanumerics and underscores.
@@ -261,6 +269,10 @@ is_name_1(_) -> false.
to_atom(A) when is_atom(A) -> A;
to_atom(S) when is_list(S) -> list_to_atom(S).
+
+to_list(A) when is_atom(A) -> atom_to_list(A);
+to_list(S) when is_list(S) -> S.
+
%% @private
unique([X | Xs]) -> [X | unique(Xs, X)];
@@ -454,20 +466,20 @@ uri_get("file://localhost/" ++ Path) ->
uri_get_file(Path);
uri_get("file://" ++ Path) ->
Msg = io_lib:format("cannot handle 'file:' scheme with "
- "nonlocal network-path: 'file://~s'.",
+ "nonlocal network-path: 'file://~ts'.",
[Path]),
{error, Msg};
uri_get("file:/" ++ Path) ->
uri_get_file(Path);
uri_get("file:" ++ Path) ->
- Msg = io_lib:format("ignoring malformed URI: 'file:~s'.", [Path]),
+ Msg = io_lib:format("ignoring malformed URI: 'file:~ts'.", [Path]),
{error, Msg};
uri_get("http:" ++ Path) ->
uri_get_http("http:" ++ Path);
uri_get("ftp:" ++ Path) ->
uri_get_ftp("ftp:" ++ Path);
uri_get("//" ++ Path) ->
- Msg = io_lib:format("cannot access network-path: '//~s'.", [Path]),
+ Msg = io_lib:format("cannot access network-path: '//~ts'.", [Path]),
{error, Msg};
uri_get([C, $:, $/ | _]=Path) when C >= $A, C =< $Z; C >= $a, C =< $z ->
uri_get_file(Path); % special case for Windows
@@ -478,7 +490,7 @@ uri_get(URI) ->
true ->
uri_get_file(URI);
false ->
- Msg = io_lib:format("cannot handle URI: '~s'.", [URI]),
+ Msg = io_lib:format("cannot handle URI: '~ts'.", [URI]),
{error, Msg}
end.
@@ -543,12 +555,12 @@ uri_get_http_1(Result, URI) ->
end.
http_errmsg(Reason, URI) ->
- io_lib:format("http error: ~s: '~s'", [Reason, URI]).
+ io_lib:format("http error: ~ts: '~ts'", [Reason, URI]).
%% TODO: implement ftp access method
uri_get_ftp(URI) ->
- Msg = io_lib:format("cannot access ftp scheme yet: '~s'.", [URI]),
+ Msg = io_lib:format("cannot access ftp scheme yet: '~ts'.", [URI]),
{error, Msg}.
%% @private
@@ -603,7 +615,7 @@ copy_file(From, To) ->
{ok, _} -> ok;
{error, R} ->
R1 = file:format_error(R),
- report("error copying '~s' to '~s': ~s.", [From, To, R1]),
+ report("error copying '~ts' to '~ts': ~ts.", [From, To, R1]),
exit(error)
end.
@@ -619,7 +631,7 @@ list_dir(Dir, Error) ->
fun (S, As) -> warning(S, As), [] end
end,
R1 = file:format_error(R),
- F("could not read directory '~s': ~s.", [filename(Dir), R1])
+ F("could not read directory '~ts': ~ts.", [filename(Dir), R1])
end.
%% @private
@@ -655,7 +667,7 @@ simplify_path(P) ->
%% ok -> ok;
%% {error, R} ->
%% R1 = file:format_error(R),
-%% report("cannot create directory '~s': ~s.", [Dir, R1]),
+%% report("cannot create directory '~ts': ~ts.", [Dir, R1]),
%% exit(error)
%% end.
@@ -677,7 +689,6 @@ try_subdir(Dir, Subdir) ->
write_file(Text, Dir, Name) ->
write_file(Text, Dir, Name, '').
-
%% @spec (Text::deep_string(), Dir::edoc:filename(),
%% Name::edoc:filename(), Package::atom()|string()) -> ok
%% @doc Like {@link write_file/3}, but adds path components to the target
@@ -685,16 +696,18 @@ write_file(Text, Dir, Name) ->
%% @private
write_file(Text, Dir, Name, Package) ->
- Dir1 = filename:join([Dir | packages:split(Package)]),
- File = filename:join(Dir1, Name),
+ write_file(Text, Dir, Name, Package, [{encoding,latin1}]).
+
+write_file(Text, Dir, Name, Package, Options) ->
+ File = filename:join([Dir, to_list(Package), Name]),
ok = filelib:ensure_dir(File),
- case file:open(File, [write]) of
+ case file:open(File, [write] ++ Options) of
{ok, FD} ->
io:put_chars(FD, Text),
ok = file:close(FD);
{error, R} ->
R1 = file:format_error(R),
- report("could not write file '~s': ~s.", [File, R1]),
+ report("could not write file '~ts': ~ts.", [File, R1]),
exit(error)
end.
@@ -705,8 +718,9 @@ write_info_file(App, Packages, Modules, Dir) ->
Ts1 = if App =:= ?NO_APP -> Ts;
true -> [{application, App} | Ts]
end,
- S = [io_lib:fwrite("~p.\n", [T]) || T <- Ts1],
- write_file(S, Dir, ?INFO_FILE).
+ S0 = [io_lib:fwrite("~p.\n", [T]) || T <- Ts1],
+ S = ["%% encoding: UTF-8\n" | S0],
+ write_file(S, Dir, ?INFO_FILE, '', [{encoding,unicode}]).
%% @spec (Name::edoc:filename()) -> {ok, string()} | {error, Reason}
%%
@@ -714,7 +728,14 @@ write_info_file(App, Packages, Modules, Dir) ->
read_file(File) ->
case file:read_file(File) of
- {ok, Bin} -> {ok, binary_to_list(Bin)};
+ {ok, Bin} ->
+ Enc = edoc_lib:read_encoding(File, []),
+ case catch unicode:characters_to_list(Bin, Enc) of
+ String when is_list(String) ->
+ {ok, String};
+ _ ->
+ {error, invalid_unicode}
+ end;
{error, Reason} -> {error, Reason}
end.
@@ -740,7 +761,7 @@ read_info_file(Dir) ->
parse_info_file(Text, File);
{error, R} ->
R1 = file:format_error(R),
- warning("could not read '~s': ~s.", [File, R1]),
+ warning("could not read '~ts': ~ts.", [File, R1]),
{?NO_APP, [], []}
end;
false ->
@@ -755,7 +776,7 @@ uri_get_info_file(Base) ->
{ok, Text} ->
parse_info_file(Text, URI);
{error, Msg} ->
- warning("could not read '~s': ~s.", [URI, Msg]),
+ warning("could not read '~ts': ~ts.", [URI, Msg]),
{?NO_APP, [], []}
end.
@@ -764,10 +785,10 @@ parse_info_file(Text, Name) ->
{ok, Vs} ->
info_file_data(Vs);
{error, eof} ->
- warning("unexpected end of file in '~s'.", [Name]),
+ warning("unexpected end of file in '~ts'.", [Name]),
{?NO_APP, [], []};
{error, {_Line,Module,R}} ->
- warning("~s: ~s.", [Module:format_error(R), Name]),
+ warning("~ts: ~ts.", [Module:format_error(R), Name]),
{?NO_APP, [], []}
end.
@@ -818,7 +839,7 @@ find_sources(Path, Pkg, Rec, Ext, Opts) ->
lists:flatten(find_sources_1(Path, to_atom(Pkg), Rec, Ext, Skip)).
find_sources_1([P | Ps], Pkg, Rec, Ext, Skip) ->
- Dir = filename:join(P, filename:join(packages:split(Pkg))),
+ Dir = filename:join(P, atom_to_list(Pkg)),
Fs1 = find_sources_1(Ps, Pkg, Rec, Ext, Skip),
case filelib:is_dir(Dir) of
true ->
@@ -846,9 +867,12 @@ find_sources_2(Dir, Pkg, Rec, Ext, Skip) ->
find_sources_3(Es, Dir, Pkg, Rec, Ext, Skip) ->
[find_sources_2(filename:join(Dir, E),
- to_atom(packages:concat(Pkg, E)), Rec, Ext, Skip)
+ to_atom(join(Pkg, E)), Rec, Ext, Skip)
|| E <- Es, is_package_dir(E, Dir)].
+join('', E) -> E;
+join(Pkg, E) -> filename:join(Pkg, E).
+
is_source_file(Name, Ext) ->
(filename:extension(Name) == Ext)
andalso is_name(filename:rootname(Name, Ext)).
@@ -858,16 +882,16 @@ is_package_dir(Name, Dir) ->
andalso filelib:is_dir(filename:join(Dir, Name)).
%% @private
-find_file([P | Ps], Pkg, Name) ->
- Dir = filename:join(P, filename:join(packages:split(Pkg))),
- File = filename:join(Dir, Name),
+find_file([P | Ps], []=Pkg, Name) ->
+ Pkg = [],
+ File = filename:join(P, Name),
case filelib:is_file(File) of
true ->
File;
false ->
find_file(Ps, Pkg, Name)
end;
-find_file([], _Pkg, _Name) ->
+find_file([], [], _Name) ->
"".
%% @private
@@ -1009,7 +1033,7 @@ run_plugin(Name, Key, Default, Fun, Opts) when is_atom(Name) ->
{ok, Value} ->
Value;
R ->
- report("error in ~s '~w': ~W.", [Name, Module, R, 20]),
+ report("error in ~ts '~w': ~W.", [Name, Module, R, 20]),
exit(error)
end.