Skip to content

Commit

Permalink
General code cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
k32 committed Nov 10, 2024
1 parent f0a016b commit fb677ae
Show file tree
Hide file tree
Showing 25 changed files with 184 additions and 473 deletions.
50 changes: 7 additions & 43 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,54 +1,18 @@
DOCBOOK := _build/lee_doc/test_out.xml
WWW := _build/lee_doc/html/index.html

MANPAGE_STYLESHEET ?= /usr/share/xml/docbook/?chap/docbook-xsl/manpages/docbook.xsl
XSLTNG := _build/lee_doc/docbook-xslTNG-2.1.2/libs/docbook-xslTNG-2.1.2.jar
all: compile linelimit test docbook_validate docs
all: compile linelimit doc

.PHONY: compile
compile:
rebar3 do dialyzer,eunit,ct,edoc,cover

.PHONY: demo
demo:
rebar3 as demo escriptize

.PHONY: linelimit
linelimit:
support/linelimit

.PHONY: docbook_validate
docbook_validate: _build/lee_doc/xsd/xlink.xsd _build/lee_doc/xsd/docbook.xsd compile
xmllint --noout --schema _build/lee_doc/xsd/docbook.xsd '_build/lee_doc/test_out.xml'

# Fetch DocBook XSD schema for testing
_build/lee_doc/xsd/docbook.xsd: _build/lee_doc/xsd
curl -o $@ https://docbook.org/xml/5.0/xsd/docbook.xsd

_build/lee_doc/xsd/xlink.xsd: _build/lee_doc/xsd
curl -o $@ https://www.w3.org/1999/xlink.xsd

_build/lee_doc/xsd:
mkdir -p $@

.PHONY: docs _build/lee_doc/man/lee.1
docs: $(WWW) $(MANPAGE)

$(MANPAGE): $(DOCBOOK)
xsltproc -o "$$(dirname $<)/../man/" $(MANPAGE_STYLESHEET) "$<"

$(DOCBOOK):
rebar3 eunit
.PHONY: doc
doc: _build/top.texi _build/top_html/index.html

$(WWW): $(DOCBOOK) $(XSLTNG)
mkdir -p "$$(dirname $@)"
cd $$(dirname $@) ;\
java -jar $(CURDIR)/$(XSLTNG) resource-base-uri='./' chunk-output-base-uri='./' \
verbatim-syntax-highlight-languages='bash erlang' \
chunk=index.html persistent-toc=true chunk-nav=true $(CURDIR)/$<
cp -R _build/lee_doc/docbook-xslTNG-2.1.2/resources/* $$(dirname $@)
_build/top.texi: compile
texi2any --info -o $@ test/top.texi

$(XSLTNG):
cd _build/lee_doc/ && \
wget https://github.com/docbook/xslTNG/releases/download/2.1.2/docbook-xslTNG-2.1.2.zip && \
unzip docbook-xslTNG-2.1.2.zip
_build/top_html/index.html: compile
texi2any --html -o $(dir $@) test/top.texi
77 changes: 15 additions & 62 deletions README.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -247,8 +247,11 @@ lee:patch(?MY_STORAGE, Patch)

== Documentation

Lee helps to generate user manuals using https://docbook.org/[Docbook] as an intermediate format.
(You don't have to write any DocBook by hand, though)
Lee can export documentation about all configurable parameters into TexInfo format (it's possible to implement exporters to other formats, but the API is currentle undocumented).
TexInfo files can be transformed to other formats, such GNU Info, HTML, PDF and EPUB.

Texinfo files generated by Lee are not self-contained.
They are meant to be included into other files, see https://github.com/k32/Lee/blob/master/test/top.texi[top.texi].

In the simplest case, it is possible to embed docstrings directly into the model:

Expand All @@ -259,71 +262,21 @@ In the simplest case, it is possible to embed docstrings directly into the model
#{ oneliner => "This value controls fooing" %% Very short description in plain text
, type => integer()
, default => 41
%% Long description in DocBook format:
, doc => "<para>This is a long and elaborate description of
the parameter using docbook markup.</para>
<para>It just goes on and on...</para>"
}}
}.
----

`oneliner` is a one-sentence summary, and `doc` is a more elaborate description formatted as DocBook.
Lee does the job of assembling an intermediate DocBook file from the fragments.
%% Long description in TexInfo format:
, doc => """
This is a long and elaborate description of the parameter using TexInfo markup.
Also element with `doc_root` metatype containing information about the application itself should be present somewhere in the model:
It just goes on and on... It can include markup, for example @b{bold text}.
[source,erlang]
----
#{ '$doc_root' =>
{[doc_root],
#{ oneliner => "The ultimate self-documenting frobnicator"
, app_name => "Frob"
, doc => "<para>Long and elaborate description of this
tool</para>"
%% Name of executable:
, prog_name => "frob"
}}
@quotation Warning
Characters @@, @{ and @} should be escaped with @@
@end quotation
"""
}}
}.
----

(Note: location of doc root node doesn't matter, but there should be one and only one node with `doc_root` metatype).

=== Why DocBook

DocBook is not the most popular or concise markup language, but it was chosen as an intermediate format because of the following properties:

* It's the easiest format to assemble from small fragments
* Erlang has great support for XML out of the box
* It's easy to validate programmatically, thanks to the XML schema
** It's easier to integrate spell checking
* It's whitespace-insensitive.
Given that the docstrings may come from string literals embedded into Erlang code,
formatting of the source code should not affect the resulting documents.
Also it generally focuses on structure rather than representation,
which is useful for extracting a diverse range of formats from HTML to manpage.

=== Asciidoc

Embedding documentation into code as XML works in simple cases, but it doesn't scale well.
In a large project it's preferable to keep documentation separate, and use a less verbose format.

Lee supports https://docs.asciidoctor.org/asciidoc/latest/[AsciiDoc] as an alternative format.
https://github.com/k32/Lee/blob/master/src/framework/lee_asciidoc.erl[lee_asciidoctor] module allows to "enrich" the model with the docstrings extracted from an external source,
see https://github.com/k32/Lee/blob/master/doc/src/schema.adoc[example].

=== Export

The job of `lee_doc` module is to produce a docbook XML file.
This can be done with XSLT stylesheets:

* https://docbook.org/tools/
Note: many Linux distributions make these stylesheets available in the repositories.
For example, in Ubuntu the package is called `docbook-xsl`.

* https://xsltng.docbook.org
xslTNG can create very fancy static HTML webpages.

https://github.com/k32/Lee/blob/master/Makefile[Makefile] gives an example of how to integrate these tools into the build flow.
`oneliner` is a one-sentence summary and `doc` is a more elaborate description formatted as TexInfo.

== Name?

Expand Down
2 changes: 1 addition & 1 deletion include/lee.hrl
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

%% Internal mnode definition
-record(mnode,
{ metatypes = [] :: ordsets:set(atom())
{ metatypes = [] :: ordsets:ordset(atom())
, metaparams = #{} :: map()
}).

Expand Down
6 changes: 2 additions & 4 deletions rebar.config
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
%% -*- mode:erlang -*-
{erl_opts, [debug_info]}.
{erl_opts, [debug_info, warnings_as_errors]}.

{escript_name, example_model2}.
{escript_emu_args, "%%! -escript main example_model2\n"}.
Expand All @@ -18,9 +18,7 @@

%{dialyzer, [{warnings, [overspecs, underspecs]}]}.

{profiles, [ {demo,
[{src_dirs, ["src", "doc/example"]}]}
, {test,
{profiles, [ {test,
[{deps, [{proper, "1.3.0"}]}]}
, {dev,
[ {plugins, [rebar3_hex]}
Expand Down
6 changes: 3 additions & 3 deletions src/framework/lee.erl
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@
]).

-export_type([node_id/0, metatype/0, type/0, mnode/0, model/0,
lee_module/0, cooked_module/0, properties/0, data/0, patch/0, patch_result/0
lee_module/0, cooked_module/0, properties/0, data/0, patch/0, patch_result/0,
validate_result/0
]).

-include_lib("typerefl/include/types.hrl").
Expand Down Expand Up @@ -71,8 +72,7 @@
%% @doc Put model to a namespace.
%%
%% `namespace([foo, bar], A)' is equivalent to `#{foo => #{bar => A}}'
-spec namespace(lee:key(), lee:module()) ->
lee:module().
-spec namespace(lee:key(), lee:lee_module()) -> lee:lee_module().
namespace(Key, M) ->
lists:foldl( fun(NodeId, Acc) ->
#{NodeId => Acc}
Expand Down
110 changes: 0 additions & 110 deletions src/framework/lee_asciidoc.erl

This file was deleted.

9 changes: 5 additions & 4 deletions src/framework/lee_doc.erl
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,17 @@
-export([texinfo/3]).

-export([documented/0]).
-export_type([doclet/0]).

-include("lee_internal.hrl").
-include_lib("typerefl/include/types.hrl").

-type doclet(Data) :: #doclet{data :: Data}.
-type doclet() :: #doclet{}.

-type docstring() :: iodata().
-reflect_type([docstring/0]).

-type formatter() :: fun((options(), io:device(), doclet(_)) -> _).
-type formatter() :: fun((options(), io:device(), doclet()) -> _).

-type options() ::
#{ output_dir := file:filename()
Expand Down Expand Up @@ -133,7 +134,7 @@ make_docs(Model, Options = #{formatter := F}) ->
end,
MTs).

-spec get_description(lee:model(), lee:model_key()) -> [doclet(docstring())].
-spec get_description(lee:model(), lee:model_key()) -> [doclet()].
get_description(Model, Key) ->
#mnode{metaparams = Attrs} = lee_model:get(Key, Model),
case Attrs of
Expand All @@ -143,7 +144,7 @@ get_description(Model, Key) ->

%% @doc Return a list with single element containing the oneliner, or
%% empty list
-spec get_oneliner(lee:model(), lee:model_key()) -> [doclet(string())].
-spec get_oneliner(lee:model(), lee:model_key()) -> [doclet()].
get_oneliner(Model, Key) ->
#mnode{metaparams = Attrs} = lee_model:get(Key, Model),
case Attrs of
Expand Down
8 changes: 4 additions & 4 deletions src/framework/lee_lib.erl
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
format(Fmt, Attrs) ->
lists:flatten(io_lib:format(Fmt, Attrs)).

-spec patch_key(lee:patch_op()) -> lee:key().
-spec patch_key(lee_storage:patch_op()) -> lee:key().
patch_key({set, K, _}) ->
K;
patch_key({rm, K}) ->
Expand Down Expand Up @@ -179,7 +179,7 @@ perform_checks(Key, Attrs, CheckFuns) ->
, typerefl:type()
, lee:properties() | #mnode{}
, boolean()
) -> lee:validate_result().
) -> {[_Error], [_Warning]}.
validate_optional_meta_attr(Attr, Type, #mnode{metaparams = MP}, WarnIfAbsent) ->
validate_optional_meta_attr(Attr, Type, MP, WarnIfAbsent);
validate_optional_meta_attr(Attr, Type, Params, WarnIfAbsent) ->
Expand All @@ -196,14 +196,14 @@ validate_optional_meta_attr(Attr, Type, Params, WarnIfAbsent) ->
-spec validate_optional_meta_attr( atom()
, typerefl:type()
, lee:properties() | #mnode{}
) -> lee:validate_result().
) -> {[_Error], [_Warning]}.
validate_optional_meta_attr(Attr, Type, #mnode{metaparams = MP}) ->
validate_optional_meta_attr(Attr, Type, MP, false).

-spec validate_meta_attr( atom()
, typerefl:type()
, lee:properties() | #mnode{}
) -> lee:validate_result().
) -> {[_Error], [_Warning]}.
validate_meta_attr(Attr, Type, #mnode{metaparams = MP}) ->
validate_meta_attr(Attr, Type, MP);
validate_meta_attr(Attr, Type, Params) ->
Expand Down
Loading

0 comments on commit fb677ae

Please sign in to comment.