diff options
Diffstat (limited to 'lib/edoc/src/edoc_lib.erl')
-rw-r--r-- | lib/edoc/src/edoc_lib.erl | 98 |
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. |