Skip to content

Commit

Permalink
improve rendering of docs in hover
Browse files Browse the repository at this point in the history
Adapts changes from elixir-lsp/elixir_sense#280
  • Loading branch information
lukaszsamson committed Oct 8, 2023
1 parent 5efc5d8 commit b61dc56
Show file tree
Hide file tree
Showing 8 changed files with 438 additions and 141 deletions.
45 changes: 45 additions & 0 deletions apps/language_server/lib/language_server/doc_links.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
defmodule ElixirLS.LanguageServer.DocLinks do
@moduledoc """
Provides links to hex docs
"""

@hex_base_url "https://hexdocs.pm"

defp get_erts_modules do
{:ok, [[erlang_lib_dir]]} = :init.get_argument(:root)
erts_version = :erlang.system_info(:version)
erts_app_path = Path.join([erlang_lib_dir, "lib", "erts-#{erts_version}", "ebin", "erts.app"])

{:ok, [{:application, _, props}]} = :file.consult(erts_app_path)
modules = Keyword.get(props, :modules)
for module <- modules, into: %{}, do: {module, {:erts, erts_version}}
end

defp get_app(module) do
module_to_app =
for {app, _, vsn} <- Application.loaded_applications(),
{:ok, app_modules} = :application.get_key(app, :modules),
mod <- app_modules,
into: %{},
do: {mod, {app, vsn}}

module_to_app
|> Map.merge(get_erts_modules())
|> Map.get(module)
end

def hex_docs_module_link(module) do
{app, vsn} = get_app(module)
"#{@hex_base_url}/#{app}/#{vsn}/#{inspect(module)}.html"
end

def hex_docs_function_link(module, function, arity) do
{app, vsn} = get_app(module)
"#{@hex_base_url}/#{app}/#{vsn}/#{inspect(module)}.html##{function}/#{arity}"
end

def hex_docs_type_link(module, type, arity) do
{app, vsn} = get_app(module)
"#{@hex_base_url}/#{app}/#{vsn}/#{inspect(module)}.html#t:#{type}/#{arity}"
end
end
40 changes: 40 additions & 0 deletions apps/language_server/lib/language_server/markdown_utils.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
defmodule ElixirLS.LanguageServer.MarkdownUtils do
# Find the lowest heading level in the fragment
defp lowest_heading_level(fragment) do
case Regex.scan(~r/(#+)/, fragment) do
[] ->
nil

matches ->
matches
|> Enum.map(fn [_, heading] -> String.length(heading) end)
|> Enum.min()
end
end

# Adjust heading levels of an embedded markdown fragment
def adjust_headings(fragment, base_level) do
min_level = lowest_heading_level(fragment)

if min_level do
level_difference = base_level + 1 - min_level

Regex.replace(~r/(#+)/, fragment, fn _, capture ->
adjusted_level = String.length(capture) + level_difference
String.duplicate("#", adjusted_level)
end)
else
fragment
end
end

def join_with_horizontal_rule(list) do
Enum.map_join(list, "\n\n---\n\n", fn lines ->
lines
|> String.replace_leading("\r\n", "")
|> String.replace_leading("\n", "")
|> String.replace_trailing("\r\n", "")
|> String.replace_trailing("\n", "")
end) <> "\n"
end
end
Loading

0 comments on commit b61dc56

Please sign in to comment.