ignatov / intellij-erlang

Erlang IDE
https://www.jetbrains.com/help/idea/2018.2/getting-started-with-erlang.html
Other
735 stars 120 forks source link

generate documentation with code module #1017

Open ignatov opened 1 year ago

ignatov commented 1 year ago

I'm trying to call code:get_doc in order to fetch documentation for standard modules.

Something like that should work, but I failed to run it.

MODULE=$1
FUNCTION=$2
ARITY=$3

erl -noshell -eval "{ok, {Docs, _}} = code:get_doc($MODULE), FunctionDocs = [Doc || #doc_v1{anno = {Function, Arity}, doc = Doc} <- Docs#docs_v1.docs, Function =:= $FUNCTION, Arity =:= $ARITY], io:format('~s~n', [FunctionDocs]), init:stop()." -run init stop > docs.txt

@kvakvs could you please assist?

kpy3 commented 1 year ago

Try this:

getdocs:

#!/usr/bin/env escript
%% -*- erlang -*-
%%! -start_epmd false

-include_lib("kernel/include/eep48.hrl").

main([Mod,Fun,Arity]) ->
  {ok, Docs} = code:get_doc(list_to_existing_atom(Mod)),
  Key ={function,list_to_existing_atom(Fun),list_to_integer(Arity)},
  {Key,_Location,FunSig,FunDocMap,Sig} = lists:keyfind(Key,1,Docs#docs_v1.docs),
  erlang:display({fun_sig, FunSig}),
  erlang:display({fun_doc_raw, maps:get(<<"en">>, FunDocMap)}),
  erlang:display({since, maps:get(since, Sig)}).
$ escript getdocs maps get 2
ignatov commented 1 year ago
-module(main).
-author("ignatov").

-export([hello/0]).

hello() ->
  Predicate = fun({{function, quote, 2}, _, _, _, _}) -> true; (_) -> false end,
  {ok, Docs} = code:get_doc(ftp),
  {docs_v1,
    _Anno,
    _BeamLanguage,
    _Format,
    _ModuleDoc,
    _Metadata,
    FunctionDocs} = Docs,

  Res = lists:filter(Predicate, FunctionDocs),
%%  io:format("~p", [Res]),
  [{_Signature, _Location, _Spec, DocMap, _EditUrlMap}] = Res,

  ErlangStructure = maps:get(<<"en">>, DocMap),

  io:format("~p", [ErlangStructure]),

  ShellDoc = shell_docs:get_doc(ftp, quote, 2),

  io:format("~p", [ShellDoc]),
%%  shell_docs:render(ftp, ShellDoc),

  io:format("~p", [ShellDoc]),

  ok.

my half-backed version is the following ;)

ignatov commented 1 year ago

even shorter

-module(doc_doc).
-author("ignatov").

%% API
-export([doc/0]).

doc() ->
  io:format("~p", [(shell_docs:get_doc(ftp, quote, 2))]).

And now I want to render it to HTML, but I don't know how to use shell_docs/render functions :)

ignatov commented 1 year ago
-module(doc_doc).
-author("ignatov").

%% API
-export([doc/0]).

doc() ->

  Module = ftp,
  Function = quote,
  Arity = 2,

  {ok, Doc} = code:get_doc(Module),
  Config = #{encoding => unicode, ansi => false, columns => 100},
  Render = shell_docs:render(Module, Function, Arity, Doc, Config),
  io:format("~p", [Render]),

  ok

.

that prints

[["\n",
  [[160,<<" quote(Pid, Command) -> [FTPLine]">>],"\n"],
  "\n",
  [[32,32,84,121,112,101,115,58,10,32,32,32,32,<<"Pid = pid()">>,10,32,32,32,
    32,<<"Command = string()">>,10,32,32,32,32,<<"FTPLine = string()">>,10,10,
    32,32,78,<<"ote">>,58,10,32,32,32,32,
    <<"The telnet end of line characters, from the FTP protocol definition, CRLF, for\n    example, \"\\\\r\\\\n\" has been removed.">>,
    10,10,32,32,
    <<"Sends an arbitrary FTP command and returns verbatim a list of the lines sent back by\n  the FTP server. This function is intended to give application accesses to FTP commands\n  that are server-specific or that cannot be provided by this FTP client.">>,
    10,10,32,32,78,<<"ote">>,58,10,32,32,32,32|
    <<"FTP commands requiring a data connection cannot be successfully issued with this\n    function.">>],
   "\n"]]]

@kpy3 or @kvakvs need yours help to go further

kvakvs commented 1 year ago

I don't get where this data is going. It will be specific for this current SDK only. Do you want to preload this when SDK is added? Can this be extracted from the AST, i think that feature with doc on mouse-over already exists and works for standard library?

ignatov commented 1 year ago

Not really, just compare.

image
kpy3 commented 1 year ago

@kpy3 or @kvakvs need yours help to go further

It looks like an iolist, so slightly modified script can output readable text:

-module(doc_doc).
-author("ignatov").

%% API
-export([doc/0]).

doc() ->

  Module = ftp,
  Function = quote,
  Arity = 2,

  {ok, Doc} = code:get_doc(Module),
  Config = #{encoding => unicode, ansi => false, columns => 100},
  Render = shell_docs:render(Module, Function, Arity, Doc, Config),
  io:format("~ts", [iolist_to_binary(Render)]),

  ok

.

output:

% erlc doc_doc.erl 
% erl -noshell -noinput -s doc_doc doc -s init stop

  -spec quote(Pid :: pid(), Cmd :: string()) -> [FTPLine :: string()].

  Note:
    The telnet end of line characters, from the FTP protocol definition, CRLF, for
    example, "\\r\\n" has been removed.

  Sends an arbitrary FTP command and returns verbatim a list of the lines sent back by
  the FTP server. This function is intended to give application accesses to FTP commands
  that are server-specific or that cannot be provided by this FTP client.

  Note:
    FTP commands requiring a data connection cannot be successfully issued with this
    function.
kpy3 commented 1 year ago

Hmmm iolist_to_binary seems unneeded and can be removed:

-module(doc_doc).
-author("ignatov").

%% API
-export([doc/0]).

doc() ->

  Module = ftp,
  Function = quote,
  Arity = 2,

  {ok, Doc} = code:get_doc(Module),
  Config = #{encoding => unicode, ansi => false, columns => 100},
  Render = shell_docs:render(Module, Function, Arity, Doc, Config),
  io:format("~ts", [Render]),

  ok

.
ignatov commented 1 year ago

Ah, ~ts. Thanks.