Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add completions of aliased modules #1

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 30 additions & 11 deletions company-elixir.el
Original file line number Diff line number Diff line change
Expand Up @@ -79,14 +79,14 @@

(defun company-elixir--candidates-filter (_process output)
"Filter OUTPUT from iex process and redirect them to company."
(let ((output-without-ansi-chars (ansi-color-apply output)))
(set-text-properties 0 (length output-without-ansi-chars) nil output-without-ansi-chars)
(let ((output-without-iex (car (split-string output-without-ansi-chars "iex"))))
(if (string-match "\\[" output-without-iex)
(let ((candidates (split-string output-without-iex "\[\],[ \f\t\n\r\v']+" t)))
(company-elixir--return-candidates candidates))))))

(defun company-elixir--find-candidates(expr)
(let* ((output-without-ansi-chars (ansi-color-apply output))
(output-without-text-props (company-elixir--remove-props-in-string output-without-ansi-chars))
(output-without-iex (car (split-string output-without-text-props "iex"))))
(if (string-match "\\[" output-without-iex)
(let ((candidates (split-string output-without-iex "\[\],[ \f\t\n\r\v']+" t)))
(company-elixir--return-candidates candidates)))))

(defun company-elixir--find-candidates(expr _aliases)
"Send request for completion to iex process with EXPR."
(process-send-string (company-elixir--process (company-elixir--project-root))
(concat "CompanyElixirServer.expand('" expr "')\n")))
Expand All @@ -100,9 +100,10 @@
(company-elixir--get-prefix)))
(candidates (cons :async
(lambda (callback)
(setq company-elixir--callback callback)
(setq company-elixir--last-completion arg)
(company-elixir--find-candidates arg))))))
(let ((aliases (company-elixir--get-matching-buffer-lines "^\s*alias.*$" (buffer-string))))
(setq company-elixir--callback callback)
(setq company-elixir--last-completion arg)
(company-elixir--find-candidates arg aliases)))))))

(defun company-elixir--return-candidates (candidates)
"Return CANDIDATES to company-mode."
Expand Down Expand Up @@ -132,10 +133,28 @@
(setq p2 (point))
(buffer-substring-no-properties p1 p2)))))

(defun company-elixir--get-matching-buffer-lines (regexp string)
"Get a list of all REGEXP that match in a STRING."
(save-match-data
(let ((pos 0)
matches)
(while (string-match regexp string pos)
(push (match-string 0 string) matches)
(setq pos (match-end 0)))
(mapcar #'company-elixir--remove-props-in-string matches))))

(defun company-elixir--remove-props-in-string (string)
"Remove text properties in STRING."
(progn
(set-text-properties 0 (length string) nil string)
string))


(defun company-elixir-hook()
"Add elixir-company to company-backends."
(add-to-list (make-local-variable 'company-backends)
'company-elixir))


(provide 'company-elixir)
;;; company-elixir ends here
68 changes: 67 additions & 1 deletion company_elixir_script.exs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,73 @@ defmodule CompanyElixirServer do
{Process.get(:evaluator), self()}
end

def expand(expr) do
defp expand(expr) do
do_expand(expr)
end

def expand(expr, alias_lines) do
if String.ends_with?(expr, ".") do
clean_expr = String.replace(expr, ".", "")
aliases = parse_aliases(alias_lines)
found_alias = Map.get(aliases, clean_expr)

if found_alias do
case do_expand(found_alias <> ".") do
:not_found -> do_expand(expr)
result -> result
end
end
else
do_expand(expr)
end
rescue
_ -> :not_found
end

defp parse_aliases(alias_lines) do
alias_lines
|> Enum.flat_map(fn line ->
parse_alias(line)
end)
|> Enum.into(%{})
end

defp parse_alias(alias_line) do
clean_alias_line =
alias_line
|> String.replace("alias", "")
|> String.trim()

cond do
String.contains?(clean_alias_line, "as:") ->
[aliased_module, name]= String.split(clean_alias_line, ", as:")

[{String.trim(name), String.trim(aliased_module)}]

String.contains?(clean_alias_line, "{") ->
[head | tail] = String.split(clean_alias_line, ["}", "{", ","])

Enum.map(tail, fn part ->
{part, head <> part}
end)

true ->
name =
clean_alias_line
|> String.split(".")
|> List.last()

[{name, clean_alias_line}]
end
end

defp do_expand(expr) when is_binary(expr) do
charlist = String.to_charlist(expr)

do_expand(charlist)
end

defp do_expand(expr) do
case IEx.Autocomplete.expand(Enum.reverse(expr), __MODULE__) do
{:yes, _, result} -> result
_ -> :not_found
Expand Down