···11+---
22+title: "Common Test for Elixir developers"
33+date: 2019-07-15T14:31:21+02:00
44+description: "What is Common Test and how we can use it in Elixir"
55+tags:
66+ - erlang
77+ - beam
88+ - elixir
99+ - testing
1010+ - programming
1111+ - common_test
1212+ - commoner
1313+---
1414+1515+In my new job I have opportunity to work a little bit more with Erlang code and
1616+Erlang related tools than earlier. That forced me a little to learn and use
1717+[Common Test][ct] library which is **the** testing library in Erlang world.
1818+When after that I needed to work back it hit me hard how much stuff I am
1919+missing in Elixir. In this article I will try to present Common Test library
2020+from the viewpoint of long standing Elixir guy and present how it compares to
2121+the ExUnit.
2222+2323+## Unit testing vs integration testing
2424+2525+The main difference between these two is their intended usage. In it's core
2626+ExUnit is intended as a library for unit testing (no surprise there, as it is
2727+literally in it's name), on the other hand Common Test is more about integration
2828+testing and looking on the system as a whole. So the discussion there would not
2929+be fair, as it isn't apples to apples, but for second let's check what makes
3030+each of them great for their intended uses:
3131+3232+ExUnit for unit testing:
3333+3434+- Simple way to setup and teardown tests via `setup` and `setup_all` macros
3535+- Built in testing of documentation examples via `doctest`
3636+- Immutability of test environment (at least that is what you should try to
3737+ achieve)
3838+- Very simple way of running different test modules in parallel (tests within
3939+ single module are always sync)
4040+- Each test run in separate process, which prevents sharing data between
4141+ processes via process dictionary
4242+- Grouping tests into `describe` blocks
4343+- In overall simplicity of the library as a whole
4444+4545+Common Test for integration testing:
4646+4747+- Persistent test results - logs, results, "generated garbage" is stored between
4848+ runs in the Common Test, which allows to track what and when happened, and if
4949+ needed trace the bug in the logs/leftovers
5050+- Generating "private directory" per suite
5151+- Grouping tests while allowing single test to be reused in different groups
5252+- Extensive control about order and parallelization of tests within groups
5353+- Built in very extensive and detailed reports (HTML and JUnit)
5454+- Distributed testing
5555+- Define dependencies between tests
5656+- Set of helpers for working with different network protocols (SSH, Telnet,
5757+ SNMP, FTP, Erlang RPC, netconf)
5858+- Built in support for data fixtures
5959+- Built in support for complex configuration of test runs via [test
6060+ specifications](http://www.erlang.org/doc/man/run_test_chapter.html#test-specification-syntax)
6161+- Built in logging (we will cover that later)
6262+6363+So as you can see, the Common Test is much broader and complex, but at the same
6464+time it provides a lot of utilities that are really helpful while writing
6565+integration tests, that can span multiple applications.
6666+6767+## Writing Common Test suite
6868+6969+While CT provides enormous power in hand of the experienced tester/developer
7070+it's API isn't the top of the class (which happen a lot in Erlang tools, whoever
7171+wanted to integrate them with anything then they will know what I mean). But in
7272+fact writing simple test suite in CT is fairly easy:
7373+7474+```erlang
7575+-module(example_SUITE). % The naming convention (with uppercase _SUITE) Erlang
7676+ % convention which allow ct to find test suites.
7777+ % Something like ExUnit _test.exs naming convention
7878+7979+-export([all/0]).
8080+8181+-export([test_function_name/1]).
8282+8383+all() ->
8484+ [test_function_name].
8585+8686+test_function_name(_Config) ->
8787+ 2 = 1 + 1.
8888+```
8989+9090+It is pretty easy and understandable format, but with due CT power it [quickly
9191+can grow to be "less" readable](https://github.com/erlang/otp/blob/81d332cc693d2be8a5af16bfbcae0bfde6702479/lib/ssh/test/ssh_algorithms_SUITE.erl#L36).
9292+Taming that power can be problematic and can cause few headaches for newcomers.
9393+9494+## Reporting
9595+9696+Another part, and the one that I miss the most in ExUnit, is reporting in Common
9797+Test. This alone is in my humble opinion **THE** best part of the library. To
9898+present you how this work assume that we have above test suite which we will run
9999+with `ct_run -dir .`. This will compile and run our tests (obviously), but in
100100+addition to that it will generate hell lot of cruft files, some JQuery (yes,
101101+this is still used in 2019), some CSS files, some HTML and other.
102102+103103+Just check [this out](/common-test-example/simple/index.html). This is example report
104104+generated by the Common Test. As you can see it contains a lot of information in
105105+quite readable format. Not only it contains informations about current run, but
106106+all previous runs as well, which is really handy when tracking regressions.
107107+108108+But can we store even more informations there? Yes, as CT includes simple
109109+logging facility it is completely possible to log your own informations during
110110+tests, for example, lets modify our test to log some informations:
111111+112112+```erlang
113113+test_function_name(_Config) ->
114114+ ct:log("Example message"),
115115+ 2 = 1 + 1.
116116+```
117117+118118+Now when we run tests again, then we will see more informations (even coloured)
119119+in [our test log](/common-test-example/log/ct_run.ct@NiunioBook.2019-07-16_11.03.21/common-test-example.log.logs/run.2019-07-16_11.03.22/example_suite.test_function_name.html):
120120+121121+
122122+123123+Additionally there is support Surefire XML output (commonly known as JUnit XML)
124124+via [hook that is distributed with Common Test](http://www.erlang.org/doc/man/ct_hooks_chapter.html#built-in-cths).
125125+This is very useful, as many CI services (for sure Jenkins, Circle CI, and
126126+GitLab CI) support such files to provide better CI results than raw stdout.
127127+128128+## Comparison to ExUnit
129129+130130+ExUnit is great tool, which is very flexible while being relatively simple.
131131+Unfortunately that simplicity makes it very lacking when comparing with "more
132132+established" solutions like Common Test which shines when we "grow out" of the
133133+ExUnit tests. It provides a lot great tools that really help with finding bugs
134134+(for example when I was joining the project and I was trying to run tests
135135+locally I have some issues due to misconfiguration, it was much easier to send
136136+tarball of the test results instead of sending wall of text captured from
137137+stdout).
138138+139139+Don't get me wrong, ExUnit is great and powerful, and for sure you should use
140140+it. It is great evolution over EUnit, but again, it would be worth of having
141141+built in [Surefire XML output](http://www.erlang.org/doc/man/eunit_surefire.html)
142142+due to it's popularity and support in many CI services.
143143+144144+## Future
145145+146146+But is everything lost and we need to fall back to the Erlang code (which can be
147147+problematic for many people) to use Common Test? Not exactly, Comcast (yes, that
148148+Comcast) [created simple wrapper][ctex] for Elixir (unfortunately seems pretty
149149+dead to me) and I have started [Commoner][commoner] library that is meant to
150150+provide API more familiar and easier to use:
151151+152152+```elixir
153153+defmodule Commoner.ExampleSuite do
154154+ use CommonTest.Suite
155155+156156+ test "foo bar" do
157157+ assert (1 + 1) in [2]
158158+ end
159159+160160+ test "bar baz" do
161161+ CommonTest.log("Hello")
162162+ end
163163+end
164164+```
165165+166166+I am very interested about your feelings about Common Test usage in Elixir and
167167+about proposed API for Commoner. You can ping me:
168168+169169+- On [Elixir forum thread about Commoner][forum]
170170+- In Twitter via `@hauleth`
171171+172172+### Special thanks
173173+174174+- José Valim - for reading it through and reviewing before publishing
175175+176176+[ct]: http://www.erlang.org/doc/man/basics_chapter.html
177177+[ctex]: https://github.com/Comcast/ctex
178178+[commoner]: https://github.com/hauleth/commoner
179179+[forum]: https://elixirforum.com/t/commoner-elixir-wrapper-for-common-test-library/23966?u=hauleth
+169
content/post/eli5-ownership.md
···11+---
22+date: 2019-07-14T17:38:48+01:00
33+description: "Simple introduction to Rust's ownership system"
44+title: "Here be (owned) books"
55+tags:
66+ - rust
77+ - programming
88+ - ownership
99+ - eli5
1010+ - borrowing
1111+---
1212+1313+One of the biggest Rust's pros is unique ownership system. Unfortunately, it is
1414+also one of the hardest thing to learn. In this article I will try to explain
1515+it the same way I had learnt it and how I introduce people to one.
1616+1717+**Disclaimer**: If you do not find this article helpful try to search another.
1818+People are different and different things *zing* them.
1919+2020+## Let's have a book
2121+2222+Ownership becomes simple and natural if you just acknowledge it as an
2323+application of real world relationship. For example imagine any type in Rust as
2424+a form of text note. We have different type of notes and basing on that, each
2525+of them we will handle differently.
2626+2727+- short ones, like phone no. of the hot waiter/waitress
2828+- longer ones, like this article
2929+- longest ones, like a *Lord of the Rings*
3030+3131+Using this analogy let my try to introduce you, dear reader, to the amazing
3232+world of Rust's ownership.
3333+3434+## One can own the book
3535+3636+Each note, no matter what size it is, can have one owner. Me, you, anyone, it
3737+doesn't matter, but there will be only one owner. You can do whatever you want
3838+with such note but with that power comes, not so great, responsibility: after
3939+you are done with this book you will need to destroy it. As you are a law
4040+abiding citizen you will recycle it in appreciate institution, but it is your
4141+responsibility to do it. Of course it is not the only way to deal with book. You
4242+can also give it to someone and then it will be her or his responsibility.
4343+4444+To rephrase it in Rust way, it would look like that:
4545+4646+```rust
4747+struct Note;
4848+4949+fn someone() {
5050+ let book = Note; // he creates the book and he owns it
5151+5252+ // here he can do whatever he want with our `book`
5353+} // at the end of his life he'll destroy all his belongings
5454+5555+fn someone_with_testament() {
5656+ let book = Note; // new book
5757+5858+ // he can do whatever he wants to do with his book
5959+6060+ someone_else(book);
6161+ // he gives her book to `someone_else`,
6262+ // altogether with responsibility to destroy it
6363+6464+ // now he cannot do anything with this book,
6565+ // as it is not his personal belonging anymore
6666+}
6767+```
6868+6969+## One can borrow the book
7070+7171+When we don't want to give someone a book (we like that one) we can also lend
7272+him one. And there are two ways to borrow one book:
7373+7474+- We can edit that book (ex. it is our personal dairy) and we lend it to someone
7575+ to check our spelling. We trust that person and we explicitly allow her to
7676+ edit our notes in place. We call it **mutable borrow**.
7777+- We do not trust one and we lend our beloved book with no permission to edit
7878+ it. Even more, that person knows, that writing something in that book will
7979+ make us go rampage and destroy whole universe. It will be **immutable
8080+ borrow**.
8181+8282+Of course if we borrow something from someone else, then we can lend it further
8383+on the same rules that was applied to us.
8484+8585+Rust also ensures that **mutable borrow** is unique. There will never be more
8686+than one person that will be allowed to edit the book. We still can create chain
8787+of trust - like when I find someone who is better at English than me, I would
8888+allow this person to correct an article written by me or my friend who has
8989+entrusted me with correcting his text.
9090+9191+**Immutable borrows** aren't exclusive. I can lend my books as many times as I
9292+want with one exception: I cannot lend a book that is still borrowed by someone
9393+who can change its content.
9494+9595+In Rust it would look like that:
9696+9797+```rust
9898+fn my() {
9999+ let mut book = Note;
100100+101101+ spelling_corrector(&mut book);
102102+ // we must explicitly mention that we lend the book
103103+ // and we not give it away
104104+105105+ reader(&book);
106106+}
107107+108108+fn spelling_corrector(book: &mut Note) {
109109+ // correct spelling in place
110110+}
111111+112112+fn reader(book: &Note) {
113113+ // read a book
114114+}
115115+```
116116+117117+## Not all notes are worth borrowing
118118+119119+Sometimes this whole process of lending and then receiving a note back is much
120120+more complicated then just cloning the whole note for someone else. Imagine that
121121+you are in school and friend wants to copy your homework. What you do is lending
122122+your homework to him, with caution he can clone it on his own. This is what
123123+Rust's `Clone` trait provides - method to clone content of struct without moving
124124+its ownership.
125125+126126+```rust
127127+#[derive(Clone)]
128128+struct Homework;
129129+130130+fn my() {
131131+ let homework = Homework;
132132+133133+ friend(&homework);
134134+}
135135+136136+fn friend(work: &Homework) { // we lend it immutably
137137+ let mut homework: Homework = work.clone();
138138+ // your friend now has his own modifiable copy
139139+}
140140+```
141141+142142+But some notes are even shorter than that. They are so short and easy to copy
143143+that it is much easier to copy them every time you need, instead of explicitly
144144+mentioning that we are making a copy - like when you give your phone number to a
145145+hot girl at the bar. This is `Copy`. Small type that can be mechanically copied
146146+each time when needed.
147147+148148+```rust
149149+#[derive(Copy, Clone)]
150150+// everything what is `Copy` must be also `Clone`
151151+struct PhoneNo;
152152+153153+fn my() {
154154+ let no = PhoneNo;
155155+156156+ hot_stuff(no);
157157+}
158158+159159+fn hot_stuff(no: PhoneNo) {
160160+ // fingers crossed
161161+}
162162+```
163163+164164+## Conclusion
165165+166166+There is more stuff to learn, but these are the basic laws of ownership in Rust.
167167+Everything else is based on those and if you learn that, it will became much
168168+easier for you to understand how other types behave and, more importantly, why
169169+they work the way they do.
+350
content/post/vim-for-elixir.md
···11+---
22+title: "Dumb Elixir VIsual (and iMproved) editor"
33+description: "How I have configured Vim for working with Elixir and Erlang projects"
44+date: 2019-04-13T21:40:05+02:00
55+tags:
66+ - elixir
77+ - erlang
88+ - vim
99+ - neovim
1010+ - programming
1111+---
1212+1313+> Earlier published on [Medium](https://medium.com/@hauleth/dumb-elixir-visual-and-improved-editor-53c23a0800e4)
1414+1515+
1616+1717+I am quite orthodox Vim user and I like to know everything that is happening in
1818+my editor configuration. By no means I am "minimal" Vim user, I currently have
1919+48 plugins installed, I just very carefully pick my plugins (few of them I have
2020+written myself) to use only plugins that I understand and I can fix on my own in
2121+case of problems. This results with configuration I understand and control in
2222+all means.
2323+2424+## What this article is not
2525+2626+This isn't "introduction into Vim" article neither "how to configure Vim for
2727+Elixir development". Here I will try to describe how I use Vim for Elixir and
2828+Erlang development, you can find some nice ideas and tips that may help you, but
2929+by any means I do not mean that this is configuration you should or should not
3030+use. You should use whatever you like (even if I do not like what you use) as
3131+long as you understand what you use and why you use that.
3232+3333+> *Any sufficiently complicated set of Vim plugins contains an ad hoc,
3434+> informally-specified, bug-ridden, slow implementation of half of Vim's
3535+> features.*
3636+> -- robertmeta's tenth rule.
3737+3838+Now we can start.
3939+4040+## Basics
4141+4242+I am using NeoVim 0.3.4, but almost everything I will describe there should work
4343+in Vim 8.1+ as well. If you will encounter any problems, then please let me
4444+know.
4545+4646+Vim doesn't (as 13.04.2019) do not support Elixir out of the box, so what we
4747+need is to install [`vim-elixir`][] plugin which will provide niceties like syntax
4848+colouring and indentation. Even if syntax colouring isn't your thing then I
4949+would still recommend installing it as it provides other things that it provides
5050+few other niceties that I will describe later.
5151+5252+But how to install it? In truly minimal setup you can just create
5353+`pack/elixir/start` directory within your `~/.vim` folder
5454+(`$XDG_CONFIG_DIR/nvim` in case of NeoVim) and clone given repository there,
5555+however I am using [`vim-packager`][] which is based on [`minpac`][] and is
5656+truly minimal package manager (it is important distinction from [`vim-plug`][]
5757+or others that also manages plugin loading, these plugins only manage fetching)
5858+which even do not need to be loaded during "normal" runtime, only when you are
5959+updating plugins.
6060+6161+## Project navigation
6262+6363+A lot of people, when come from other editors, often install NERDTree to have
6464+"project drawer" functionality within Vim, because this is what they are used
6565+to. Unfortunately "[split windows and the project drawer go together like oil
6666+and vinegar][oil-and-vinegar]" and it can result in painful experience or, which
6767+is even worse, avoiding built in functionalities, because these do not mix well.
6868+Vim comes with built in NetRW plugin for working with remote files and directory
6969+tries. However for me this plugin is bloated as well and I would love to get rid
7070+of it (unfortunately it is not currently possible as few functionalities relies
7171+on it, namely dictionaries) so I replaced everything with [`dirvish`][].
7272+Additionally I often use fuzzy finder, which in my case is [`vim-picker`][] with
7373+[`fzy`][] which for me is much faster and more precise than popular FZF.
7474+7575+These tools are great when we are navigating in tree that is new to us or do not
7676+have explicit structure. When we are working on Elixir projects then we know
7777+before hand that there will be some commonly shared structure, like
7878+`lib/<name>.ex` will contain source code, `test/<name>_test.exs` will contain
7979+test files, etc. What is more we know that `<name>` part will be shared between
8080+file and its unit tests. This is very powerful assumption, as this allow us to
8181+use [`vim-projectionist`][] with ease. This plugin provide 3 main
8282+functionalities (for me):
8383+8484+- Jumping to the files basing on their path, so for example I can use `:Elib
8585+ foo` to automatically jump to file `lib/foo.ex`. It doesn't seems like much,
8686+ but it also provides fuzzy finding, and allows me to define more specific
8787+ matches, like `:Econtroller foo` will open
8888+ `lib/app_web/controllers/foo_controller.ex` (not exactly that as I use
8989+ different project layout, but that is topic on another article).
9090+- File templates, so when I start editing file (doesn't matter how I opened it,
9191+ so this do not require to use above `:Elib` command), so when I start editing
9292+ test file it automatically add scaffold which I can configure per project.
9393+- Alternate files which in short are "related" files. For example when I edit
9494+ file `lib/foo/bar/baz.ex` and I run `:A` it will create (if not exist) and
9595+ jump to the file `test/foo/bar/baz_test.exs` which will be already scaffolded
9696+ by the earlier functionality. Recently it even became possible to have
9797+ multiple alternates.
9898+9999+Whole plugin is configured by `.projections.json` file, but it would be
100100+infeasible to add this file to each project you work for. Fortunately there is
101101+solution for that, we can define "heuristics" that will try to match for given
102102+project structure and provide such features "globally". My configuration for
103103+that looks like this:
104104+105105+```vim
106106+let g:projectionist_heuristics['mix.exs'] = {
107107+ \ 'apps/*/mix.exs': { 'type': 'app' },
108108+ \ 'lib/*.ex': {
109109+ \ 'type': 'lib',
110110+ \ 'alternate': 'test/{}_test.exs',
111111+ \ 'template': ['defmodule {camelcase|capitalize|dot} do', 'end'],
112112+ \ },
113113+ \ 'test/*_test.exs': {
114114+ \ 'type': 'test',
115115+ \ 'alternate': 'lib/{}.ex',
116116+ \ 'template': [
117117+ \ 'defmodule {camelcase|capitalize|dot}Test do',
118118+ \ ' use ExUnit.Case',
119119+ \ '',
120120+ \ ' alias {camelcase|capitalize|dot}, as: Subject',
121121+ \ '',
122122+ \ ' doctest Subject',
123123+ \ 'end'
124124+ \ ],
125125+ \ },
126126+ \ 'mix.exs': { 'type': 'mix' },
127127+ \ 'config/*.exs': { 'type': 'config' },
128128+ \ '*.ex': {
129129+ \ 'makery': {
130130+ \ 'lint': { 'compiler': 'credo' },
131131+ \ 'test': { 'compiler': 'exunit' },
132132+ \ 'build': { 'compiler': 'mix' }
133133+ \ }
134134+ \ },
135135+ \ '*.exs': {
136136+ \ 'makery': {
137137+ \ 'lint': { 'compiler': 'credo' },
138138+ \ 'test': { 'compiler': 'exunit' },
139139+ \ 'build': { 'compiler': 'mix' }
140140+ \ }
141141+ \ }
142142+ \ }
143143+144144+let g:projectionist_heuristics['rebar.config'] = {
145145+ \ '*.erl': {
146146+ \ 'template': ['-module({basename}).', '', '-export([]).', ''],
147147+ \ },
148148+ \ 'src/*.app.src': { 'type': 'app' },
149149+ \ 'src/*.erl': {
150150+ \ 'type': 'src',
151151+ \ 'alternate': 'test/{}_SUITE.erl',
152152+ \ },
153153+ \ 'test/*_SUITE.erl': {
154154+ \ 'type': 'test',
155155+ \ 'alternate': 'src/{}.erl',
156156+ \ },
157157+ \ 'rebar.config': { 'type': 'rebar' }
158158+ \ }
159159+```
160160+161161+### This will provide:
162162+163163+#### For Elixir:
164164+165165+- `lib` that will contain project source files which will be already filled with
166166+ module named `Foo.BarBaz` for file named `lib/foo/bar_baz.ex` (jump by `:Elib
167167+ foo/bar_baz`)
168168+- `test` for test files which will be instantiated with module named
169169+ `Foo.BarBazTest` for file `test/foo/bar_baz_test.exs` that will already use
170170+ `ExUnit.Case` (you can jump via `:Etest foo/bar_baz`), will define
171171+ `alias Foo.BarBaz, as: Subject`, and will run doctests for that module
172172+- `config` for configuration files
173173+- `mix` for `mix.exs`
174174+175175+It will also define test files as default alternates for each source file (and
176176+vice versa, because alternate files do not need to be symmetric), so if you
177177+run `:A` in file `lib/foo/bar_baz.ex` it will automatically jump to the
178178+`test/foo/bar_baz_test.exs`.
179179+180180+#### For Erlang:
181181+182182+- `src` for source files
183183+- `app` for `*.app.src` files
184184+- `test` for common test suites
185185+- `rebar` for `rebar.config` file
186186+187187+The relation between source files and test files is exactly the same as in
188188+Elixir projects.
189189+190190+One thing can bring your attention, why the hell I define helpers for `mix.exs`
191191+and `rebar.config` as you can simply use `:e <file>`. The answer is simple, `:e`
192192+will work for files in Vim working directory while `:E` will work form the
193193+projectionist root, aka directory where is `.projections.json` file defined (or
194194+in case of heuristics, from the directory that matched files). This mean that
195195+when I edit files in umbrella application I can use `:Emix` (or `:Erebar`) to
196196+edit current sub-project config file and `:e mix.exs` to edit global one.
197197+198198+## Completion and language server
199199+200200+For completion and code formatting I use [`vim-lsp`][]. I have tried most of the
201201+language server clients out there, but I always come back to this one for a few
202202+reasons:
203203+204204+- It is implemented only in VimL which mean that I am not forced to installing
205205+ any compatibility layers or fighting with different runtimes.
206206+- It is simple enough that I can easily dig into it, and fix problems that I
207207+ have encountered.
208208+- It doesn't override any built in Vim functionality and instead provide set of
209209+ commands that you can then bind to whatever mappings you want.
210210+- It do not force me to use autocompletion, which I do not use at all. At the
211211+ same time it provides seamless integration with built-in Vim functionality of
212212+ omnicompletion and user completion by providing `lsp#complete` function.
213213+214214+This approach of not providing default mappings is really nice for power users,
215215+as this allow us to define everything on our own. For example some of plugins
216216+use <kbd><C-]></kbd> for jumping to definition, which I often use (it is
217217+jump to tag definition) and shadowing it would be problematic for me. So in the
218218+end I have created my own set of mappings, that have additional feature of being
219219+present only if there is any server that supports them:
220220+221221+```vim
222222+func! s:setup_ls(...) abort
223223+ let l:servers = lsp#get_whitelisted_servers()
224224+225225+ for l:server in l:servers
226226+ let l:cap = lsp#get_server_capabilities(l:server)
227227+228228+ if has_key(l:cap, 'completionProvider')
229229+ setlocal omnifunc=lsp#complete
230230+ endif
231231+232232+ if has_key(l:cap, 'hoverProvider')
233233+ setlocal keywordprg=:LspHover
234234+ endif
235235+236236+ if has_key(l:cap, 'definitionProvider')
237237+ nmap <silent> <buffer> gd <plug>(lsp-definition)
238238+ endif
239239+240240+ if has_key(l:cap, 'referencesProvider')
241241+ nmap <silent> <buffer> gr <plug>(lsp-references)
242242+ endif
243243+ endfor
244244+endfunc
245245+246246+augroup LSC
247247+ autocmd!
248248+ autocmd User lsp_setup call lsp#register_server({
249249+ \ 'name': 'ElixirLS',
250250+ \ 'cmd': {_->['elixir-ls']},
251251+ \ 'whitelist': ['elixir', 'eelixir']
252252+ \})
253253+ autocmd User lsp_setup call lsp#register_server({
254254+ \ 'name': 'RLS',
255255+ \ 'cmd': {_->['rls']},
256256+ \ 'whitelist': ['rust']
257257+ \})
258258+ autocmd User lsp_setup call lsp#register_server({
259259+ \ 'name': 'solargraph',
260260+ \ 'cmd': {server_info->['solargraph', 'stdio']},
261261+ \ 'initialization_options': {"diagnostics": "true"},
262262+ \ 'whitelist': ['ruby'],
263263+ \ })
264264+ autocmd User lsp_setup call lsp#register_server({
265265+ \ 'name': 'dot',
266266+ \ 'cmd': {server_info->['dot-language-server', '--stdio']},
267267+ \ 'whitelist': ['dot'],
268268+ \ })
269269+270270+ autocmd User lsp_server_init call <SID>setup_ls()
271271+ autocmd BufEnter * call <SID>setup_ls()
272272+augroup END
273273+```
274274+275275+## Running tasks and linting
276276+277277+A lot of people "cannot live" without lint-as-you-type feature, but I think,
278278+that not using such functionality makes me a less sloppy and better programmer.
279279+It makes me to think when I write and do not rely on some magical friend that
280280+will always watch over my shoulder. However when the problem happens in my code
281281+I would like to know where and quickly jump to the place where error occurred.
282282+Additionally I would like to run tasks in the background without interruption to
283283+my current work. All of it became possible with introduction of asynchronous
284284+tasks in NeoVim and Vim 8. So I have created plugin [`asyncdo.vim`][] that
285285+allows me to easily implement `:Make` command that works exactly like built
286286+in [`:make`][], but do not halt my normal work. Together with [`vim-makery`][]
287287+(which nicely integrates with `vim-projectionsit`) and built in functionality of
288288+[`:compiler`][], which is supported by `vim-elixir`, it allows me to easily run all
289289+sorts of commands very easily. If you look into projectionist heuristics above
290290+you will see that there is `"makery"` key defined for `*.ex` and `*.exs` files.
291291+That allows me to run `:Mlint %` to run Credo on current file and the results
292292+will be present within QuickFix window which together with my [`qfx.vim`][] will
293293+mark lines with errors using signs. In the same manner I can run `:Mtest` to run
294294+tests for whole project and have failed tasks visible in QuickFix window.
295295+296296+## Other utilities
297297+298298+There is bunch of other plugins that are quite helpful when it comes to working
299299+on Elixir projects and do not interfere with Vim features, ex.:
300300+301301+- [`vim-dadbod`][] which allows you to run SQL queries from within Vim, and [I
302302+ have written integration with Ecto][ecto-dadbod] which is provided with
303303+ `vim-elixir` by default. So if you are working on Elixir application that has
304304+ `MyApp.Repo` Ecto repository then you can run `:DB MyApp.Repo` and Vim will
305305+ open your DB client within separate terminal that will be connected to your DB
306306+- [`vim-endwise`][] that will automatically add end to your do blocks
307307+- [`direnv.vim`][] simplify management of environment variables in per-directory
308308+ manner
309309+- [`vim-editorconfig`][] ([sgur][]'s one, not official one) - pure VimL support
310310+ for [EditorConfig][] files
311311+312312+## Summary
313313+314314+I hope that you find some nice ideas within this article that will help in
315315+improving your own Vim configuration without adding much clutter.
316316+317317+No, I will not publish my own `vimrc` in fear that some of you will copy it as
318318+is (also not that this is particularly troublesome for anyone who is aware of
319319+Google to find it). Instead I highly suggest You to dig into your own
320320+configuration and for each line ask yourself:
321321+322322+323323+- Do I know what this line **does**?
324324+- Do I really **need** this line?
325325+326326+And if answer for any of these questions is **no** then remove such line. In the
327327+end you either learn what for it was, or that you never needed it.
328328+329329+[`dirvish`]: https://github.com/justinmk/vim-dirvish
330330+[oil-and-vinegar]: http://vimcasts.org/blog/2013/01/oil-and-vinegar-split-windows-and-project-drawer/
331331+[`vim-elixir`]: https://github.com/elixir-editors/vim-elixir
332332+[`vim-packager`]: https://github.com/kristijanhusak/vim-packager
333333+[`minpac`]: https://github.com/k-takata/minpac
334334+[`vim-plug`]: https://github.com/junegunn/vim-plug
335335+[`vim-picker`]: https://github.com/srstevenson/vim-picker
336336+[`fzy`]: https://github.com/jhawthorn/fzy
337337+[`vim-projectionist`]: https://github.com/tpope/vim-projectionist
338338+[`vim-lsp`]: https://github.com/prabirshrestha/vim-lsp
339339+[`asyncdo.vim`]: https://github.com/hauleth/asyncdo.vim
340340+[`vim-makery`]: https://github.com/igemnace/vim-makery
341341+[`qfx.vim`]: https://gitlab.com/hauleth/qfx.vim
342342+[`vim-dadbod`]: https://github.com/tpope/vim-dadbod
343343+[`vim-endwise`]: https://github.com/tpope/vim-endwise
344344+[`direnv.vim`]: https://github.com/direnv/direnv.vim
345345+[`vim-editorconfig`]: https://github.com/sgur/vim-editorconfig
346346+[sgur]: https://github.com/sgur
347347+[ecto-dadbod]: https://github.com/elixir-editors/vim-elixir/pull/481
348348+[EditorConfig]: https://editorconfig.org
349349+[`:make`]: https://vimhelp.org/quickfix.txt.html#%3Amake
350350+[`:compiler`]: https://vimhelp.org/quickfix.txt.html#%3Acompiler