aboutsummaryrefslogtreecommitdiffstats
path: root/lib/edoc/src/edoc_run.erl
diff options
context:
space:
mode:
Diffstat (limited to 'lib/edoc/src/edoc_run.erl')
-rw-r--r--lib/edoc/src/edoc_run.erl225
1 files changed, 225 insertions, 0 deletions
diff --git a/lib/edoc/src/edoc_run.erl b/lib/edoc/src/edoc_run.erl
new file mode 100644
index 0000000000..37025d6621
--- /dev/null
+++ b/lib/edoc/src/edoc_run.erl
@@ -0,0 +1,225 @@
+%% =====================================================================
+%% This library is free software; you can redistribute it and/or modify
+%% it under the terms of the GNU Lesser General Public License as
+%% published by the Free Software Foundation; either version 2 of the
+%% License, or (at your option) any later version.
+%%
+%% This library is distributed in the hope that it will be useful, but
+%% WITHOUT ANY WARRANTY; without even the implied warranty of
+%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+%% Lesser General Public License for more details.
+%%
+%% You should have received a copy of the GNU Lesser General Public
+%% License along with this library; if not, write to the Free Software
+%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+%% USA
+%%
+%% $Id$
+%%
+%% @copyright 2003 Richard Carlsson
+%% @author Richard Carlsson <[email protected]>
+%% @see edoc
+%% @end
+%% =====================================================================
+
+%% @doc Interface for calling EDoc from Erlang startup options.
+%%
+%% The following is an example of typical usage in a Makefile:
+%% ```docs:
+%% erl -noshell -run edoc_run application "'$(APP_NAME)'" \
+%% '"."' '[{def,{vsn,"$(VSN)"}}]'
+%% '''
+%% (note the single-quotes to avoid shell expansion, and the
+%% double-quotes enclosing the strings).
+%%
+%% <strong>New feature in version 0.6.9</strong>: It is no longer
+%% necessary to write `-s init stop' last on the command line in order
+%% to make the execution terminate. The termination (signalling success
+%% or failure to the operating system) is now built into these
+%% functions.
+
+-module(edoc_run).
+
+-export([file/1, application/1, packages/1, files/1, toc/1]).
+
+-import(edoc_report, [report/2, error/1]).
+
+
+%% @spec application([string()]) -> none()
+%%
+%% @doc Calls {@link edoc:application/3} with the corresponding
+%% arguments. The strings in the list are parsed as Erlang constant
+%% terms. The list can be either `[App]', `[App, Options]' or `[App,
+%% Dir, Options]'. In the first case {@link edoc:application/1} is
+%% called instead; in the second case, {@link edoc:application/2} is
+%% called.
+%%
+%% The function call never returns; instead, the emulator is
+%% automatically terminated when the call has completed, signalling
+%% success or failure to the operating system.
+
+application(Args) ->
+ F = fun () ->
+ case parse_args(Args) of
+ [App] -> edoc:application(App);
+ [App, Opts] -> edoc:application(App, Opts);
+ [App, Dir, Opts] -> edoc:application(App, Dir, Opts);
+ _ ->
+ invalid_args("edoc_run:application/1", Args)
+ end
+ end,
+ run(F).
+
+%% @spec files([string()]) -> none()
+%%
+%% @doc Calls {@link edoc:files/2} with the corresponding arguments. The
+%% strings in the list are parsed as Erlang constant terms. The list can
+%% be either `[Files]' or `[Files, Options]'. In the first case, {@link
+%% edoc:files/1} is called instead.
+%%
+%% The function call never returns; instead, the emulator is
+%% automatically terminated when the call has completed, signalling
+%% success or failure to the operating system.
+
+files(Args) ->
+ F = fun () ->
+ case parse_args(Args) of
+ [Files] -> edoc:files(Files);
+ [Files, Opts] -> edoc:files(Files, Opts);
+ _ ->
+ invalid_args("edoc_run:files/1", Args)
+ end
+ end,
+ run(F).
+
+%% @spec packages([string()]) -> none()
+%%
+%% @doc Calls {@link edoc:application/2} with the corresponding
+%% arguments. The strings in the list are parsed as Erlang constant
+%% terms. The list can be either `[Packages]' or `[Packages, Options]'.
+%% In the first case {@link edoc:application/1} is called instead.
+%%
+%% The function call never returns; instead, the emulator is
+%% automatically terminated when the call has completed, signalling
+%% success or failure to the operating system.
+
+packages(Args) ->
+ F = fun () ->
+ case parse_args(Args) of
+ [Packages] -> edoc:packages(Packages);
+ [Packages, Opts] -> edoc:packages(Packages, Opts);
+ _ ->
+ invalid_args("edoc_run:packages/1", Args)
+ end
+ end,
+ run(F).
+
+%% @hidden Not official yet
+toc(Args) ->
+ F = fun () ->
+ case parse_args(Args) of
+ [Dir, Paths] -> edoc:toc(Dir,Paths);
+ [Dir, Paths, Opts] -> edoc:toc(Dir,Paths,Opts);
+ _ ->
+ invalid_args("edoc_run:toc/1", Args)
+ end
+ end,
+ run(F).
+
+
+%% @spec file([string()]) -> none()
+%%
+%% @deprecated This is part of the old interface to EDoc and is mainly
+%% kept for backwards compatibility. The preferred way of generating
+%% documentation is through one of the functions {@link application/1},
+%% {@link packages/1} and {@link files/1}.
+%%
+%% @doc Calls {@link edoc:file/2} with the corresponding arguments. The
+%% strings in the list are parsed as Erlang constant terms. The list can
+%% be either `[File]' or `[File, Options]'. In the first case, an empty
+%% list of options is passed to {@link edoc:file/2}.
+%%
+%% The following is an example of typical usage in a Makefile:
+%% ```$(DOCDIR)/%.html:%.erl
+%% erl -noshell -run edoc_run file '"$<"' '[{dir,"$(DOCDIR)"}]' \
+%% -s init stop'''
+%%
+%% The function call never returns; instead, the emulator is
+%% automatically terminated when the call has completed, signalling
+%% success or failure to the operating system.
+
+file(Args) ->
+ F = fun () ->
+ case parse_args(Args) of
+ [File] -> edoc:file(File, []);
+ [File, Opts] -> edoc:file(File, Opts);
+ _ ->
+ invalid_args("edoc_run:file/1", Args)
+ end
+ end,
+ run(F).
+
+-spec invalid_args(string(), list()) -> no_return().
+
+invalid_args(Where, Args) ->
+ report("invalid arguments to ~s: ~w.", [Where, Args]),
+ shutdown_error().
+
+run(F) ->
+ wait_init(),
+ case catch {ok, F()} of
+ {ok, _} ->
+ shutdown_ok();
+ {'EXIT', E} ->
+ report("edoc terminated abnormally: ~P.", [E, 10]),
+ shutdown_error();
+ Thrown ->
+ report("internal error: throw without catch in edoc: ~P.",
+ [Thrown, 15]),
+ shutdown_error()
+ end.
+
+wait_init() ->
+ case erlang:whereis(code_server) of
+ undefined ->
+ erlang:yield(),
+ wait_init();
+ _ ->
+ ok
+ end.
+
+%% When and if a function init:stop/1 becomes generally available, we
+%% can use that instead of delay-and-pray when there is an error.
+
+shutdown_ok() ->
+ %% shut down emulator nicely, signalling "normal termination"
+ init:stop().
+
+shutdown_error() ->
+ %% delay 1 second to allow I/O to finish
+ receive after 1000 -> ok end,
+ %% stop emulator the hard way with a nonzero exit value
+ halt(1).
+
+parse_args([A | As]) when is_atom(A) ->
+ [parse_arg(atom_to_list(A)) | parse_args(As)];
+parse_args([A | As]) ->
+ [parse_arg(A) | parse_args(As)];
+parse_args([]) ->
+ [].
+
+parse_arg(A) ->
+ case catch {ok, edoc_lib:parse_expr(A, 1)} of
+ {ok, Expr} ->
+ case catch erl_parse:normalise(Expr) of
+ {'EXIT', _} ->
+ report("bad argument: '~s':", [A]),
+ exit(error);
+ Term ->
+ Term
+ end;
+ {error, _, D} ->
+ report("error parsing argument '~s'", [A]),
+ error(D),
+ exit(error)
+ end.