elixir: add flycheck support for mix compile
This commit is contained in:
parent
8fc53ae311
commit
dd572af071
|
@ -5,6 +5,8 @@
|
|||
* Table of Contents :TOC_4_gh:noexport:
|
||||
- [[#description][Description]]
|
||||
- [[#install][Install]]
|
||||
- [[#configuration][Configuration]]
|
||||
- [[#flycheck-support-for-mix-compile][Flycheck support for mix compile]]
|
||||
- [[#key-bindings][Key bindings]]
|
||||
- [[#refcard][Refcard]]
|
||||
- [[#help][Help]]
|
||||
|
@ -18,7 +20,6 @@
|
|||
- [[#code-definition-jump][Code Definition Jump]]
|
||||
|
||||
* Description
|
||||
|
||||
This layer adds support for [[http://elixir-lang.org/][Elixir]] .
|
||||
|
||||
[[https://github.com/tonini/alchemist.el][Alchemist]] brings the Elixir tooling to Emacs and comes with a bunch of
|
||||
|
@ -32,16 +33,38 @@ features like:
|
|||
- Smart code completion
|
||||
- Elixir project management
|
||||
- Integration with [[http://company-mode.github.io/][company-mode]]
|
||||
- Flycheck support for mix compile
|
||||
|
||||
* Install
|
||||
To use this configuration layer, add it to your =~/.spacemacs=. You will need to
|
||||
add =elixir= to the existing =dotspacemacs-configuration-layers= list in this
|
||||
file.
|
||||
|
||||
* Configuration
|
||||
** Flycheck support for mix compile
|
||||
*Important:*
|
||||
Elixir compilation is based on macros and is unsafe since arbitrary code can
|
||||
be run during compilation. Therefore Spacemacs disable compilation flycheck
|
||||
support by default.
|
||||
|
||||
To enable flycheck support for =mix compile= *globally* the variable
|
||||
=elixir-enable-compilation-checking= must be explicitly set to =t= in your
|
||||
dotfile.
|
||||
|
||||
It is recommended to use directory local variables instead. These variables are
|
||||
stored in a file named =.dit-local.el= at the root of your project. Their values
|
||||
are applied only for the project and not outside. To easily add a directory
|
||||
local variable used ~SPC f v d~ and provide the mode =elixir-mode= then the
|
||||
variable name =elixir-enable-compilation-checking= and its value.
|
||||
|
||||
Spacemacs marks the variable =elixir-enable-compilation-checking= as safe so
|
||||
Emacs won't ask you if the variable is safe whenever an elixir file is opened.
|
||||
|
||||
Remember that you can check the flycheck checkers enabled with ~SPC e v~.
|
||||
|
||||
* Key bindings
|
||||
|
||||
** Refcard
|
||||
|
||||
You find and overview of all the key-bindings on the [[file:alchemist-refcard.pdf][Alchemist-Refcard]].
|
||||
|
||||
** Help
|
||||
|
|
|
@ -11,5 +11,11 @@
|
|||
|
||||
;; Variables
|
||||
|
||||
(defvar elixir-enable-compilation-checking nil
|
||||
"If non-nil syntax checking is enable for compilation.
|
||||
Default is nil because Elixir compilation is based on macros and thus it
|
||||
is unsafe. Activate this option only for trusted code, usage of a
|
||||
directory variable is recommended.")
|
||||
|
||||
(spacemacs|defvar-company-backends elixir-mode)
|
||||
(spacemacs|defvar-company-backends alchemist-iex-mode)
|
||||
|
|
|
@ -14,3 +14,14 @@
|
|||
(newline-and-indent)
|
||||
(forward-line -1)
|
||||
(indent-according-to-mode)))
|
||||
|
||||
(defun spacemacs//elixir-enable-compilation-checking ()
|
||||
"Enable compile checking if `elixir-enable-compilation-checking' is non nil."
|
||||
(message "djeoifhwfwfjegweifh")
|
||||
(hack-dir-local-variables)
|
||||
(let ((enabled (cdr (assq 'elixir-enable-compilation-checking
|
||||
file-local-variables-alist))))
|
||||
(message "---> %s" (assq 'elixir-enable-compilation-checking
|
||||
file-local-variables-alist))
|
||||
(when (or enabled elixir-enable-compilation-checking)
|
||||
(elixir-flycheck-mix-compile-setup))))
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
;;; elixir-flycheck-mix-compile.el --- Elixir flycheck integration -*- lexical-binding: t; -*-
|
||||
|
||||
;; Copyright (C) 2016 Tomasz Kowal
|
||||
|
||||
;; Author: Tomasz Kowal <tomekowal@gmail.com>
|
||||
;; Keywords: Elixir flycheck mix
|
||||
;; Version: 0.0.1
|
||||
|
||||
;; This program is free software; you can redistribute it and/or modify
|
||||
;; it under the terms of the GNU General Public License as published by
|
||||
;; the Free Software Foundation, either version 3 of the License, or
|
||||
;; (at your option) any later version.
|
||||
|
||||
;; This program is distributed in the hope that it will be useful,
|
||||
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
;; GNU General Public License for more details.
|
||||
|
||||
;; You should have received a copy of the GNU General Public License
|
||||
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
;;; Commentary:
|
||||
|
||||
;; This package should be distributed with =mix_compile_helper=.
|
||||
;; Make sure it is in your PATH
|
||||
|
||||
;;; Code:
|
||||
(require 'flycheck)
|
||||
|
||||
;; :command uses source-original, source-inplace copies the file
|
||||
;; which makes mix throw errors
|
||||
(flycheck-define-checker
|
||||
elixir-mix-compile
|
||||
"Defines a checker for elixir with mix compile"
|
||||
:command ("mix_compile_helper" source-original)
|
||||
:error-patterns
|
||||
((warning line-start
|
||||
(file-name)
|
||||
":"
|
||||
line
|
||||
": warning: "
|
||||
(message)
|
||||
line-end)
|
||||
(error line-start
|
||||
"** ("
|
||||
(one-or-more word)
|
||||
"Error) "
|
||||
(file-name)
|
||||
":"
|
||||
line
|
||||
": "
|
||||
(message)
|
||||
line-end))
|
||||
:modes (elixir-mode))
|
||||
|
||||
;;;###autoload
|
||||
(defun elixir-flycheck-mix-compile-setup ()
|
||||
"Setup Flycheck for Elixir."
|
||||
(add-to-list 'flycheck-checkers 'elixir-mix-compile))
|
||||
|
||||
(provide 'elixir-flycheck-mix-compile)
|
||||
;;; elixir-flycheck-mix-compile.el ends here
|
|
@ -0,0 +1,71 @@
|
|||
#!/usr/bin/env elixir
|
||||
defmodule :mix_compile_helper do
|
||||
def run() do
|
||||
project_root = get_project_root()
|
||||
|
||||
if project_root do
|
||||
{stdout, exit_status} =
|
||||
System.cmd "mix", ["compile", "--ignore-module-conflict"],
|
||||
cd: project_root, stderr_to_stdout: true
|
||||
stdout
|
||||
|> String.split("\n")
|
||||
|> Enum.map(&(make_paths_absolute(&1, project_root)))
|
||||
|> Enum.join("\n")
|
||||
|> IO.puts
|
||||
exit({:shutdown, exit_status})
|
||||
else
|
||||
usage(:root_not_found)
|
||||
end
|
||||
end
|
||||
|
||||
def usage(:general) do
|
||||
file = __ENV__.file |> Path.split |> List.last
|
||||
IO.puts "Usage:"
|
||||
IO.puts "Make sure executable is in the path. Run inside mix project"
|
||||
IO.puts " #{file}"
|
||||
end
|
||||
def usage(:root_not_found) do
|
||||
IO.puts "mix.exs not detected in the directory structure"
|
||||
usage(:general)
|
||||
end
|
||||
|
||||
defp make_paths_absolute(line, root) do
|
||||
line
|
||||
|> make_error_paths_absolute(root)
|
||||
|> make_warning_paths_absolute(root)
|
||||
end
|
||||
|
||||
defp make_error_paths_absolute(line, root) do
|
||||
replace_at_position_if_pattern(line, "CompileError", 2, root)
|
||||
end
|
||||
|
||||
defp make_warning_paths_absolute(line, root) do
|
||||
replace_at_position_if_pattern(line, "warning:", 0, root)
|
||||
end
|
||||
|
||||
defp replace_at_position_if_pattern(line, pattern, position, root) do
|
||||
if String.contains?(line, pattern) do
|
||||
line
|
||||
|> String.split(" ")
|
||||
|> List.update_at(position, &(Path.absname(&1, root)))
|
||||
|> Enum.join(" ")
|
||||
else
|
||||
line
|
||||
end
|
||||
end
|
||||
|
||||
def get_project_root do
|
||||
System.cwd
|
||||
|> Path.split
|
||||
|> Enum.reverse
|
||||
|> get_project_root
|
||||
end
|
||||
def get_project_root([]), do: nil
|
||||
def get_project_root([_|rest] = reversed_path) do
|
||||
current_path = reversed_path |> Enum.reverse |> Path.join()
|
||||
mix_file = Path.join(current_path, "mix.exs")
|
||||
if File.exists?(mix_file), do: current_path, else: get_project_root(rest)
|
||||
end
|
||||
end
|
||||
|
||||
:mix_compile_helper.run
|
|
@ -13,11 +13,19 @@
|
|||
'(
|
||||
alchemist
|
||||
company
|
||||
(elixir-flycheck-mix-compile
|
||||
:location local
|
||||
:toggle (configuration-layer/package-usedp 'flycheck))
|
||||
elixir-mode
|
||||
flycheck
|
||||
popwin
|
||||
smartparens
|
||||
))
|
||||
|
||||
(defun elixir/post-init-company ()
|
||||
(spacemacs|add-company-hook elixir-mode)
|
||||
(spacemacs|add-company-hook alchemist-iex-mode))
|
||||
|
||||
(defun elixir/init-alchemist ()
|
||||
(use-package alchemist
|
||||
:defer t
|
||||
|
@ -109,9 +117,35 @@
|
|||
(evil-define-key 'normal mode
|
||||
(kbd "q") 'quit-window))))
|
||||
|
||||
(defun elixir/post-init-company ()
|
||||
(spacemacs|add-company-hook elixir-mode)
|
||||
(spacemacs|add-company-hook alchemist-iex-mode))
|
||||
(defun elixir/init-elixir-flycheck-mix-compile ()
|
||||
(use-package elixir-flycheck-mix-compile
|
||||
:commands (elixir-flycheck-mix-compile-setup)
|
||||
:init
|
||||
(progn
|
||||
(add-to-list 'safe-local-variable-values
|
||||
(cons 'elixir-enable-compilation-checking nil))
|
||||
(add-to-list 'safe-local-variable-values
|
||||
(cons 'elixir-enable-compilation-checking t))
|
||||
(add-hook 'elixir-mode-hook
|
||||
'spacemacs//elixir-enable-compilation-checking t))
|
||||
:config
|
||||
;; enable mix_compile_helper executable
|
||||
(let ((layer-path (configuration-layer/get-layer-path 'elixir)))
|
||||
(add-to-list 'exec-path
|
||||
(concat layer-path
|
||||
"elixir/local/elixir-flycheck-mix-compile")))))
|
||||
|
||||
(defun elixir/init-elixir-mode ()
|
||||
(use-package elixir-mode
|
||||
:defer t))
|
||||
|
||||
(defun elixir/post-init-flycheck ()
|
||||
(add-hook 'elixir-mode-hook 'flycheck-mode))
|
||||
|
||||
(defun elixir/pre-init-popwin ()
|
||||
(spacemacs|use-package-add-hook popwin
|
||||
:post-config
|
||||
(push '("*mix*" :tail t :noselect t) popwin:special-display-config)))
|
||||
|
||||
(defun elixir/post-init-smartparens ()
|
||||
(spacemacs|use-package-add-hook smartparens
|
||||
|
@ -129,13 +163,3 @@
|
|||
:when '(("SPC" "RET"))
|
||||
:post-handlers '(:add spacemacs//elixir-do-end-close-action)
|
||||
:actions '(insert))))))
|
||||
|
||||
(defun elixir/init-elixir-mode ()
|
||||
(use-package elixir-mode
|
||||
:defer t))
|
||||
|
||||
(defun elixir/pre-init-popwin ()
|
||||
(spacemacs|use-package-add-hook popwin
|
||||
:post-config
|
||||
(push '("*mix*" :tail t :noselect t) popwin:special-display-config)))
|
||||
|
||||
|
|
Loading…
Reference in New Issue