Já mencionei as motivações de utilizar Vim no "Vim: O meu editor favorito". E embora eu já tenha "caído em tentação" e utilizado Atom e Spacemacs (esse último é simplesmente fantástico), acabo sempre retornando ao Vim. Principalmente após o lançamento da versão 8, onde processamento assíncrono foi adicionado ao editor.
Ter o Vim configurado para trabalhar com projetos Python é em teoria algo simples (se você optar por usar extensões). O problema é que durante a seleção de ferramentas, alguns detalhes aparecem e interferem na construção de um ambiente de desenvolvimento capaz de operar sem problemas.
E como diz o poeta: O diabo está nos detalhes.
Para começar é preciso selecionar um sistema de empacotamento, afim de facilitar a instalação e remoção de plugins. Embora o editor possua um mecanismo built-in em sua versão mais recente, o vim-plug mostra-se muito (mas muito) mais simples de usar.
Para instalar o vim-plug:
curl -fLo ~/.vim/autoload/plug.vim --create-dirs \
https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim
O controle dos plugins é feito através do .vimrc
:
" ~/.vimrc
call plug#begin('~/.vim/plugged')
" Lista de plugins
call plug#end()
Uma vez que o plugin desejado fora adicionado ao .vimrc
, o comando
:PlugInstall
fará o download e instalação do pacote.
Syntax highlighting é um dos recursos mais básicos (e úteis) que qualquer editor de texto possa oferecer. É no mínimo curioso o quanto a disposição de cores facilita na leitura de códigos-fonte.
O vim-polyglot suporta dezenas de linguagens (incluindo Python, claro), e o próprio projeto alega que a sua utilização não prejudica o startup time do editor. Logo, uma excelente opção caso o usuário não queira perder tempo fazendo setup desse tipo de feature:
" ~/.vimrc
call plug#begin('~/.vim/plugged')
" Lista de plugins
Plug 'sheerun/vim-polyglot'
call plug#end()
Para uma rápida instalação, execute :source $MYVIMRC
(para atualizar o .vimrc
em memória) e
em seguida :PlugInstall
.
O Asynchronous Lint Engine é um desses projetos que foram feitos para tirar o máximo da nova versão do Vim. A sua função é na realidade servir de interface assíncrona para linters de diferentes linguagens, resultando em validações do código-fonte sem travar a UI do editor.
Uma "traquinagem" que ajuda no uso do ALE é utilizar o parâmetro do
, do vim-plug, tornando
mais fácil a instalação dos utilitários necessários para que o plugin funcione:
" ~/.vimrc
(...)
Plug 'w0rp/ale', { 'do': 'pip install flake8 isort yapf' }
call plug#end()
Importante notar que se o Vim for aberto dentro de um virtualenv,
os pacotes Python serão instalados no ambiente virtual ativo. Para contornar esse problema,
e tornar essas ferramentas "globais", é possível utilizar o pyenv.
Executar :PlugInstall!
para cada virtualenv pode ser uma opção também.
Caso algo não esteja funcionando, o :ALEInfo
dará dicas de onde o problema está escondido.
O flake8 assegura que o código escrito esteja dentro das convenções da PEP8. Alguns alertas aparecerão na tela do editor quando alguma violação acontecer:
O ALE possui o conceito de "fixers". Eles são executados para realizar reparos no código-fonte
aberto, sem a necessidade da chamada de nenhum comando adicional. Em um arquivo Python, o :ALEFixSuggest
trará sugestões de fixers para a linguagem:
Try the following fixers appropriate for the filetype:
'add_blank_lines_for_python_control_statements' - Add blank lines before control statements.
'autopep8' - Fix PEP8 issues with autopep8.
'isort' - Sort Python imports with isort.
'yapf' - Fix Python files with yapf.
Try the following generic fixers:
'remove_trailing_lines' - Remove all blank lines at the end of a file.
'trim_whitespace' - Remove all trailing whitespace characters at the end of every line.
See :help ale-fix-configuration
Press q to close this window
O isort
é uma ferramenta muito útil que ajuda na ordenação dos import
Python. Já o
yapf formatará
os arquivos respeitando a PEP8.
Para habilitar esses recursos, basta adicionar a seguinte configuração ao ~/.vimrc
:
" ~/.vimrc
(...)
call plug#end()
let g:ale_fix_on_save = 1
let g:ale_fixers = {
\ 'python': [
\ 'isort',
\ 'yapf',
\ 'remove_trailing_lines',
\ 'trim_whitespace'
\ ]
\}
Com o g:ale_fix_on_save = 1
, ao salvar o arquivo os fixers serão executados automaticamente.
É possível executá-los também através do comando :ALEFix
.
Embora o YouCompleteMe seja a opção standard para autocomplete no Vim, foi no completor que eu encontrei um bom balanço entre complexidade e benefícios.
Utilizando o engine de async do Vim 8, o plugin é capaz de entregar code completion de uma maneira muito rápida, e ainda possui uma boa abstração a semantic completion (que fará o autocomplete funcionar "de fato" no caso do Python).
O jedi é o utilitário "hors concours" para essa tarefa:
" ~/.vimrc
(...)
Plug 'maralla/completor.vim', { 'do': 'pip install jedi' }
call plug#end()
A dica de usar pyenv ou de instalar para cada virtualenv (do tópico de Lint), vale aqui também.
E falando de jedi, o jedi-vim
é outra figurinha carimbada nos .vimrc
de muitos desenvolvedores Python. Assim como o
completor, ele fornece autocompletion e uma excelente ferramenta de static analysis.
Se você programa somente em Python, esqueça o completor e use apenas o jedi-vim. Caso contrário, se você programa em mais linguagens, o completor ainda é uma opção atraente (por ser "genérico").
Além do completion o jedi-vim tem outras funcionalidades que são muito úteis para lidar com grandes projetos:
<leader>g
)<leader>d
)K
)<leader>r
)<leader>n
)Portanto, é sempre útil tê-lo no seu ambiente de desenvolvimento:
" ~/.vimrc
(...)
Plug 'davidhalter/jedi-vim', { 'do': 'pip install jedi' }
call plug#end()
(...)
let g:jedi#completions_enabled = 0
A última linha acima é essencial para que o completion do jedi-vim não conflite com o do completor.
Aqui eu vou "chover no molhado" e indicar NERDTree e ctrlp.vim.
O primeiro exibe um simpático file explorer no lado esquerdo do editor, muito útil quando você não faz ideia do que está procurando, e tem que ter uma visão dos arquivos e diretórios do projeto:
Com o uso do nerdtree-git-plugin ele fica ainda mais interessante, pois sinaliza os arquivos que sofreram modificações dentro de um repositório Git.
Já o ctrlp.vim é usado para buscas de arquivos e buffers. Muito útil para quando você já tem ideia do que vai procurar:
A instalação através do vim-plug é simples, como sempre:
" ~/.vimrc
(...)
Plug 'ctrlpvim/ctrlp.vim'
Plug 'scrooloose/nerdtree' | Plug 'Xuyuanp/nerdtree-git-plugin'
call plug#end()
(...)
Bônus: O ack.vim é um excelente plugin para buscas por conteúdo.
O vim-test é um dos meus plugins favoritos! Ele é um wrapper que executa testes de diferentes granularidades, ou seja, executa o teste de um arquivo apenas, da suíte inteira, do mais próximo, do último testado, etc.
" ~/.vimrc
(...)
Plug 'janko-m/vim-test'
call plug#end()
(...)
let test#python#runner = 'pytest'
No exemplo acima, o runner configurado foi o pytest,
mas dentro do ecossistema Python ele suporta os seguintes frameworks de testes: PyTest
, Django
, Nose
, Nose2
, e PyUnit
.
É possível evocar o plugin para os diferentes níveis de testes através dos comandos :TestNearest
, :TestFile
, :TestSuite
, :TestLast
e :TestVisit
.
Bônus: Utilizando o dispatch.vim como strategy no vim-test, será possível executar os testes assincronamente.
Com o dispatch.vim, do Tim Pope, é possível executar comandos (como por exemplo, build ou testes) de forma assíncrona. O plugin se responsabiliza por escolher a melhor plataforma (tmux, tela, iTerm, headless, etc) de acordo com o ambiente no qual o Vim está rodando.
O plugin (até o momento) não utiliza a estratégia de jobs do Vim 8. Mas discussões sobre o assunto tem ocorrido, e é possível que uma solução seja incorporada em breve. Se utilizar o async do Vim é um desejo, o asyncrun.vim pode ser uma melhor opção.
Com o tmux, tanto o vim-test quanto o dispatch.vim ficam ainda mais interessantes:
Interessado no tmux? O bugsnag possui um bom artigo sobre tmux + Vim.
O .vimrc
abaixo é o resultado de todos os plugins apresentados nesse artigo:
" ~/.vimrc
call plug#begin('~/.vim/plugged')
" Lista de plugins
Plug 'sheerun/vim-polyglot'
Plug 'w0rp/ale', { 'do': 'pip install flake8 isort yapf' }
Plug 'maralla/completor.vim', { 'do': 'pip install jedi' }
Plug 'davidhalter/jedi-vim'
Plug 'ctrlpvim/ctrlp.vim'
Plug 'scrooloose/nerdtree' | Plug 'Xuyuanp/nerdtree-git-plugin'
Plug 'janko-m/vim-test'
Plug 'tpope/vim-dispatch'
call plug#end()
" Ale
let g:ale_fix_on_save = 1
let g:ale_fixers = {
\ 'python': [
\ 'isort',
\ 'yapf',
\ 'remove_trailing_lines',
\ 'trim_whitespace'
\ ]
\}
" Jedi
let g:jedi#completions_enabled = 0
" vim-test
let test#python#runner = 'pytest'
Embora haja uma vertente que defende o uso mínimo (ou nulo) de plugins no Vim, para mim eles são um dos pontos altos do editor e sem dúvida são os responsáveis por me ajudar a manter uma boa produtividade. Se você, assim como eu, não tem a mínima pretensão de ser um "vim-master", use sem medo. Tenho certeza que eles te ajudarão a lidar com os problemas do dia a dia.
Até a próxima.