Last active
March 12, 2020 15:28
-
-
Save garazdawi/68527d92ae5b37c8f129bfbdfffdfa68 to your computer and use it in GitHub Desktop.
rewrite-seealso
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env escript | |
%% -*- erlang -*- | |
%%! +A 1 +SDio 1 +S 1 -mode minimal | |
%% This script can be used to convert <seealso> to <see*> | |
%% Invoked like this: | |
%% find lib/*/doc/src system/doc/*/ erts/doc/src/ '(' -name *.xml -o -name *.xmlsrc ')' -exec ./rewrite-seealso.escript {} \; | |
%% You need a OTP with built documentation for this to work | |
main([File]) -> | |
io:format("Parse: ~s~n",[File]), | |
{ok, B} = file:read_file(File), | |
CurrApp = | |
case string:lexemes(File,"/") of | |
["erts"|_] -> | |
"erts"; | |
["lib",App|_] -> | |
{lib,App}; | |
["system","doc",App|_] -> | |
{system,App} | |
end, | |
case get_link_type(B) of | |
T when T =:= ignore; CurrApp =:= {system,"xml"} -> | |
ok; | |
Type -> | |
_NewB = replace_seealso(B, {Type,CurrApp}), | |
file:write_file(File, _NewB), | |
%% io:format("~s",[_NewB]), | |
ok | |
end. | |
get_link_type(B) when is_binary(B) -> | |
case {re:run(B, <<"<erlref>">>), | |
re:run(B, <<"<appref>">>), | |
re:run(B, <<"<comref>">>), | |
re:run(B, <<"<cref>">>), | |
re:run(B, <<"<fileref>">>), | |
re:run(B, <<"<chapter>">>)} of | |
{{match,_},_,_,_,_,_} -> | |
"seeerl"; | |
{_,{match,_},_,_,_,_} -> | |
"seeapp"; | |
{_,_,{match,_},_,_,_} -> | |
"seecom"; | |
{_,_,_,{match,_},_,_} -> | |
"seecref"; | |
{_,_,_,_,{match,_},_} -> | |
"seefile"; | |
{_,_,_,_,_,{match,_}} -> | |
"seeguide"; | |
_ -> | |
{match, _} = re:run(B, <<"<application|<part|<specs|<internal">>), | |
ignore | |
end; | |
get_link_type(File) -> | |
{ok,B} = file:read_file(File), | |
get_link_type(B). | |
replace_seealso(Bin, [{Start,Len},Space,Marker,Content], {LinkType, CurrApp}) -> | |
ModFun = | |
fun(App,Mod) -> | |
case code:which(binary_to_atom(Mod)) of | |
non_existing -> | |
LMod = binary_to_list(Mod), | |
Pats = | |
case App of | |
"erts" -> | |
[lists:concat(["erts/doc/xml/",LMod,".xml"]), | |
lists:concat(["erts/doc/xml/",LMod,"_cmd.xml"])]; | |
{system,SApp} -> | |
[lists:concat(["system/doc/xml/",SApp,"/",LMod,".xml"])]; | |
{lib,LApp} -> | |
[lists:concat(["lib/",LApp,"/doc/xml/",LMod,".xml"]), | |
lists:concat(["lib/",LApp,"/doc/xml/",LMod,"_app.xml"]), | |
lists:concat(["lib/",LApp,"/doc/xml/",LMod,"_cmd.xml"])] | |
end, | |
case lists:flatmap(fun filelib:wildcard/1, Pats) of | |
[File] -> | |
get_link_type(File); | |
Else -> | |
io:format("Could not resolve link: ~s (~p)~n", | |
[part(Bin,Marker), Else]), | |
erlang:halt(1) | |
end; | |
_ -> | |
"seeerl" | |
end | |
end, | |
Rules = | |
[{"^([^:]+:)?([^#]+)?#[^/]+/.+", | |
%% app:mod#func/ari | |
fun(_) -> | |
"seemfa" | |
end}, | |
{"^([^#]*#)type-(.*)", | |
%% #type-anchor | |
fun([_,Mod,Anchor]) -> | |
{[Mod,Anchor],"seetype"} | |
end}, | |
{"^#.*", | |
%% #anchor | |
fun([_]) -> | |
%% A local link | |
LinkType | |
end}, | |
{"^doc/([^:/]+):([^#]+)(#.+)?", | |
%% doc/system:guide#anchor | |
fun ([_,System,<<"users_guide">>|_]) -> | |
{["system/",System,":index"],"seeguide"}; | |
([_,System,Guide|T]) -> | |
{["system/",System,":",Guide|T], ModFun({system,binary_to_list(System)}, Guide)} | |
end}, | |
{"^([^:/]+):([^#]+)(#.+)?", | |
%% app:mod#anchor | |
fun ([_,App,<<"index">>|_]) -> | |
{[App,":index"],"seeapp"}; | |
([_,App,<<"users_guide">>|_]) -> | |
{[App,":index"],"seeguide"}; | |
([_,<<"erts">>,Mod|_]) -> | |
ModFun("erts",Mod); | |
([_,App,Mod|_]) -> | |
ModFun({lib,binary_to_list(App)},Mod) | |
end}, | |
{"^([^#:/]+)(#.+)?", | |
%% mod#anchor | |
fun ([_,<<"index">>|_]) -> | |
{"index","seeapp"}; | |
([_,<<"users_guide">>|_]) -> | |
{"index","seeguide"}; | |
([_,Mod|_]) -> ModFun(CurrApp,Mod) end} | |
], | |
NewLink = run_rules(Bin, Rules, [Space,Marker,Content]), | |
% io:format("NewLink: ~p~n",[NewLink]), | |
Before = part(Bin, 0, Start), | |
After = part(Bin, Start + Len, byte_size(Bin) - (Start + Len)), | |
[Before,NewLink,After]. | |
replace_seealso(B,State) -> | |
case re:run(B, <<"<seealso(\\s+)marker\\s*=\\s*\"([^\"]+)\">((?U).*)</seealso>">>, | |
[{capture,all},dotall,unicode]) of | |
{match,Match} -> | |
replace_seealso(replace_seealso(iolist_to_binary(B),Match,State),State); | |
nomatch -> | |
B | |
end. | |
run_rules(Bin, [{Pat,Fun}|T], [Space,Marker,Content] = M) -> | |
case re:run(binary:part(Bin,Marker),Pat,[{capture,all,binary},unicode]) of | |
{match,Match} -> | |
case Fun(Match) of | |
{NewMarker, LinkType} -> | |
["<",LinkType,part(Bin, Space), | |
"marker=\"",NewMarker,"\">", | |
part(Bin, Content),"</",LinkType,">"]; | |
LinkType -> | |
["<",LinkType,part(Bin, Space), | |
"marker=\"",part(Bin, Marker),"\">", | |
part(Bin, Content),"</",LinkType,">"] | |
end; | |
nomatch -> | |
run_rules(Bin, T, M) | |
end; | |
run_rules(Bin, [], [_Space,Marker,_Content]) -> | |
io:format("No rule found for \"~s\"~n",[part(Bin,Marker)]), | |
erlang:halt(). | |
part(_Bin,{-1,0}) -> | |
<<>>; | |
part(Bin, Part) -> | |
binary:part(Bin,Part). | |
part(Bin,Pos,Len) -> | |
part(Bin,{Pos,Len}). |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment