anchor.diff:  -record(state, {modules}).
   
   -ifdef(OTP_RELEASE).
  -    -record(uri_map, {host, port}).
       -if(?OTP_RELEASE >= 23).
       -include_lib("kernel/include/eep48.hrl").
       -else.
  
positive.code: get_local_doc(Missing, None) when None =:= none; None =:= #{} ->
      [{p,[],[<<"There is no documentation for ">>,Missing]}].
  
  set_proxy() ->
      % get proxyUrl configuration
      ActualProxy = gen_lsp_config_server:proxy(),
      %systemProxy
      ProxyUrl = lsp_utils:to_string(ActualProxy),
      %error_logger:info_msg("set_proxy : ~p~n", [ProxyUrl]),
      case length(ProxyUrl) of
      L when L > 0 ->
          {ok, {_Scheme, _UserInfo, Host, Port, _Path, _Query}} = parse_uri(ProxyUrl),
          % if proxy is on localhost, NoProxy should not contains localhost 
          NoProxy = case string:to_lower(Host) of
              "localhost" -> [];
              "127.0.0.1" -> [];
              _ -> ["localhost"]
          end,
  	    %error_logger:info_msg("proxy info : ~p, ~p~n", [Host, Port]),
          httpc:set_options([{proxy, {{Host, Port}, NoProxy}}]),
          proxy_set;
      _ -> noproxy
      end.
  
  -ifdef(OTP_RELEASE).
  parse_uri(Url) ->
      #uri_map{host = Host, port=Port} = uri_string:parse(Url),
      {ok, Host, Port}.
  -else.
  parse_uri(Url) ->
      {ok, {_Scheme, _UserInfo, Host, Port, _Path, _Query}} = http_uri:parse(Url),
      {ok, Host, Port}.
  -endif.
  
  get_page_lines(Module, Modules) ->
      case Modules of
          #{Module := Lines} = _ ->
              {Lines, Modules};
          _ ->
              try set_proxy()
  			catch
  			_:Err -> error_logger:info_msg("set_proxy failed: ~p~n", [Err])
  			end,
              %httpc:set_options([{proxy, {{"www-proxy.mycompany.com", 8000}, ["localhost"]}}]),
              Result = httpc:request("http://erlang.org/doc/man/" ++ atom_to_list(Module) ++ ".html"),
              case Result of
                  {ok, {_, _, Body}} ->
                      Lines = lists:map(fun (Line) ->
                          case re:run(Line, <<"^ *(.*)$">>) of
                              {match, [_, {Start, Len}]} -> binary:part(Line, Start, Len);
                              _ -> Line
                          end
                      end, binary:split(list_to_binary(Body), <<"\n">>, [global, trim])),
                      {Lines, Modules#{Module => Lines}};
                  _ ->
                      {undefined, Modules}
              end
      end.
  
  extract_function(Function, Lines) ->
      FunctionBinary = list_to_binary(atom_to_list(Function)),
      {Extracted, Completed} = lists:foldl(fun
          (Line, {undefined, false}) ->
              case binary:match(Line, <<"name=\"", FunctionBinary/binary>>) of
                  nomatch -> {undefined, false};
                  _ -> {Line, false}
              end;
          (<<>>, {Contents, false}) ->
              {Contents, true};
          (Line, {Contents, false}) ->
              NameEq = binary:match(Line, <<"name=\"">>),
              case NameEq of
                  {Start, _} ->
                      MyNameEq = binary:match(Line, <<"name=\"", FunctionBinary/binary>>),
                      case MyNameEq of
                          {Start, _} -> {<<Contents/binary, " ", Line/binary>>, false};
                          _ -> {Contents, true}
                      end;
                  _ ->
                      {<<Contents/binary, " ", Line/binary>>, false}
              end;
          (_Line, {Contents, true}) ->
              {Contents, true}
      end, {undefined, false}, Lines),
      case Completed of
          true -> Extracted;
          _ -> undefined
      end.
  
  markdown(undefined) ->
      undefined;
  markdown(Text) ->
      markdown(Text, <<>>, []).
  
  markdown(Text, Output, TagsStack) ->
      case re:run(Text, <<"^< *(/?) *([a-zA-Z0-9]+)([^>]*)>(.*)$">>) of
          nomatch ->
              case re:run(Text, <<"^([^<]+)(.*)$">>) of
                  nomatch ->
                      <<Output/binary, Text/binary>>;
                  {match, [_, OutsideTag, Rest]} ->
                      OutsideTagText = binary:part(Text, OutsideTag),
                      markdown(binary:part(Text, Rest), <<Output/binary, OutsideTagText/binary>>, TagsStack)
              end;
          {match, [_, {_, EndTagSlashLen}, Tag, Attributes, Rest]} ->
              {Processed, UpdatedTagsStack} = if
                  EndTagSlashLen > 0 ->
                      end_tag(TagsStack);
                  true ->
                      tag(binary:part(Text, Tag), binary:part(Text, Attributes), TagsStack)
              end,
              markdown(binary:part(Text, Rest), <<Output/binary, Processed/binary>>, UpdatedTagsStack)
      end.
  
  tag(_Tag, _Attributes, [off | TagsStackTail]) ->
      {<<>>, [off | [off | TagsStackTail]]};
  tag(<<"br">>, _Attributes, TagsStack) ->
      {<<"  \n">>, TagsStack};
  tag(<<"p">>, _Attributes, TagsStack) ->
      {<<>>, [<<"  \n">> | TagsStack]};
  tag(<<"dt">>, _Attributes, TagsStack) ->
      {<<"  \n**">>, [<<"**  \n">> | TagsStack]};
  tag(<<"strong">>, _Attributes, TagsStack) ->
      {<<" **">>, [<<"** ">> | TagsStack]};
  tag(<<"h3">>, Attributes, TagsStack) ->
      case re:run(Attributes, <<"func-types-title">>) of
          nomatch ->
              {<<"\n#### ">>, [<<"\n">> | TagsStack]};
          _ ->
              {<<"  \n">>, [<<"  \n">> | TagsStack]}
      end;
  tag(_Tag, Attributes, TagsStack) ->
      case re:run(Attributes, <<"bold_code">>) of
          nomatch ->
              case re:run(Attributes, <<"name=">>) of
                  nomatch ->
                      case re:run(Attributes, <<"REFTYPES|func-types-title">>) of
                          nomatch ->
                              case re:run(Attributes, <<"REFBODY">>) of
                                  nomatch -> {<<>>, [<<>> | TagsStack]};
                                  _ -> {<<"  \n">>, [<<>> | TagsStack]}
                              end;
                          _ ->
                              {<<>>, [off | TagsStack]}
                      end;
                  _ ->
                      {<<>>, [<<"  \n">> | TagsStack]}
              end;
          _ ->
              {<<" **">>, [<<"**">> | TagsStack]}
      end.
  
  end_tag([off | TagsStackTail]) ->
      {<<>>, TagsStackTail};
  end_tag([TagsStackTop | TagsStackTail]) ->
      {TagsStackTop, TagsStackTail};
  end_tag(TagsStack) ->
      {<<>>, TagsStack}.
  
  handle_cast(stop, State) ->
      {stop, normal, State}.
  
  
negative.code: handle_call({get_help, Module, Function}, _From, State) ->
      %gen_lsp_server:lsp_log("get_help for ~p:~p",[Module,Function]),
      {Reply, Modules} = case get_help_eep48(Module, Function) of
          {error, _} ->
              {undefined, State#state.modules};
          Help ->
              FlattenHelp = list_to_binary(lists:flatten(Help)),
              %gen_lsp_server:lsp_log("Help:~p",[FlattenHelp]),
  