%%-------------------------------------------------------------------- %% %% %CopyrightBegin% %% %% Copyright Ericsson AB 2010. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in %% compliance with the License. You should have received a copy of the %% Erlang Public License along with this software. If not, it can be %% retrieved online at http://www.erlang.org/. %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and limitations %% under the License. %% %% %CopyrightEnd% %% %%----------------------------------------------------------------- %% File: otp_man_index.erl %% %% Description: %% This file generates the module overview in the documentation. %% %%----------------------------------------------------------------- -module(otp_man_index). -export([gen/1, gen/2]). -include_lib("kernel/include/file.hrl"). gen([Source, RootDir, OutFile]) when is_atom(RootDir), is_atom(OutFile)-> gen(Source, RootDir, OutFile). gen(RootDir, OutFile) -> gen(rel, RootDir, OutFile). gen(Source, RootDir, OutFile) -> Bases = [{"../lib/", filename:join(RootDir, "lib")}, {"../", RootDir}], Apps = find_application_paths(Source, Bases), RefPages = find_ref_files(Apps), gen_html(RefPages, atom_to_list(OutFile)). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Find Reference files %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% find_ref_files(Apps) -> find_ref_files(Apps, []). find_ref_files([], Acc) -> Acc; find_ref_files([{App, Vsn, AppPath, RelPath} |Apps], Acc) -> case filelib:wildcard(filename:join(AppPath, "*.html")) of [] -> find_ref_files(Apps, Acc); Result -> Refs1 = lists:filter(fun(Ref) -> case file:read_file(Ref) of {ok, Bin} -> case re:run(Bin, ".*<!-- refpage -->.*",[]) of {match, _} -> true; nomatch -> false end; {error, Reason} -> exit(io_lib:format("~p : ~s\n", [Reason, Ref])) end end, Result), Refs2 = lists:map(fun(Ref) -> Module = filename:basename(Ref, ".html"), {string:to_lower(Module), Module, App ++ "-" ++ Vsn, RelPath, filename:join(RelPath, filename:basename(Ref))} end, Refs1), find_ref_files(Apps, Refs2 ++ Acc) end. find_application_paths(_, []) -> []; find_application_paths(Source, [{URL, Dir} | Paths]) -> AppDirs = get_app_dirs(Dir), AppPaths = get_app_paths(Source, AppDirs, URL), AppPaths ++ find_application_paths(Source, Paths). get_app_paths(src, AppDirs, URL) -> Sub1 = "doc/html", lists:map( fun({App, AppPath}) -> VsnFile = filename:join(AppPath, "vsn.mk"), VsnStr = case file:read_file(VsnFile) of {ok, Bin} -> case re:run(Bin, ".*VSN\s*=\s*([0-9\.]+).*",[{capture,[1],list}]) of {match, [V]} -> V; nomatch -> exit(io_lib:format("No VSN variable found in ~s\n", [VsnFile])) end; {error, Reason} -> exit(io_lib:format("~p : ~s\n", [Reason, VsnFile])) end, AppURL = URL ++ App ++ "-" ++ VsnStr, {App, VsnStr, AppPath ++ "/" ++ Sub1, AppURL ++ "/" ++ Sub1} end, AppDirs); get_app_paths(rel, AppDirs, URL) -> Sub1 = "doc/html", lists:map( fun({App, AppPath}) -> [AppName, VsnStr] = string:tokens(App, "-"), AppURL = URL ++ App, {AppName, VsnStr, AppPath ++ "/" ++ Sub1, AppURL ++ "/" ++ Sub1} end, AppDirs). get_app_dirs(Dir) -> {ok, Files} = file:list_dir(Dir), AFiles = lists:map(fun(File) -> {File, filename:join([Dir, File])} end, Files), lists:zf(fun is_app_with_doc/1, AFiles). is_app_with_doc({"." ++ _ADir, _APath}) -> false; is_app_with_doc({ADir, APath}) -> case file:read_file_info(filename:join([APath, "info"])) of {ok, _FileInfo} -> {true, {ADir, APath}}; _ -> false end. gen_html(RefPages, OutFile)-> case file:open(OutFile, [write]) of {ok, Out} -> io:fwrite(Out, "~s\n", [html_header()]), SortedPages = lists:sort(RefPages), lists:foreach(fun({_,Module, App, AppDocDir, RefPagePath}) -> io:fwrite(Out, " <TR>\n",[]), io:fwrite(Out, " <TD><A HREF=\"~s\">~s</A></TD>\n", [RefPagePath, Module]), io:fwrite(Out, " <TD><A HREF=\"~s\">~s</A></TD>\n", [filename:join(AppDocDir, "index.html"), App]), io:fwrite(Out, " </TR>\n",[]) end, SortedPages), {Year, _, _} = date(), io:fwrite(Out, "~s\n", [html_footer(integer_to_list(Year))]); {error, Reason} -> exit("~p: ~s\n",[Reason, OutFile]) end. html_header() -> "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n" "<!-- This file was generated by the otp_man_index -->\n" "<HTML>\n" "<HEAD>\n" " <link rel=\"stylesheet\" href=\"otp_doc.css\" type=\"text/css\"/>\n" " <TITLE>Erlang/OTP Manual Page Index</TITLE>\n" "</HEAD>\n" "<BODY BGCOLOR=\"#FFFFFF\" TEXT=\"#000000\" LINK=\"#0000FF\" VLINK=\"#FF00FF\" ALINK=\"#FF0000\">\n" "<CENTER>\n" "<!-- A HREF=\"http://www.erlang.org/\">\n" "<img alt=\"Erlang logo\" src=\"erlang-logo.png\"/>\n" "</A><BR -->\n" "<SMALL>\n" "[<A HREF=\"index.html\">Up</A> | <A HREF=\"http://www.erlang.org/\">Erlang</A>]\n" "</SMALL><BR>\n" "<P/><FONT SIZE=\"+4\">OTP Reference Page Index</FONT><BR>\n" "</CENTER>\n" "<CENTER>\n" "<P/>\n" "<TABLE BORDER=1>\n" "<TR>\n" " <TH>Manual Page</TH><TH>Application</TH>\n" "</TR>\n". html_footer(Year) -> "</TABLE>\n" "</CENTER>\n" "<P/>\n" "<CENTER>\n" "<HR/>\n" "<SMALL>\n" "Copyright © 1991-" ++ Year ++ "\n" "<a href=\"http://www.ericsson.com/technology/opensource/erlang/\">\n" "Ericsson AB</a>\n" "</SMALL>\n" "</CENTER>\n" "</BODY>\n" "</HTML>\n".