1/17/2013

Vim jako Python IDE

Wstęp

Trochę mi zajęło zabranie się za napisanie tego posta, ale oto jest. Mam nadzieję, że Ci się przyda. Post pisany trochę po to by utrwalić wiedzę, trochę po to, aby pomóc innym, którzy chcą spróbować Vima i trochę po to, by mieć coś ciekawego na tym blogu.

Zacznę od tego dlaczego nie inne edytory. Wypróbowałem naprawdę mnóstwo różnych IDE do Pythona, zaczynając od Eclipse, poprzez PyCharm, Komodo, erci5, Sublime Text 2 i wiele wiele innych, na Wingware kończąc. Wszystko z czego korzystałem po pewnym czasie albo i na początku "muliło", miało mnóstwo opcji z których nie skorzystałem i pewnie nie skorzystam nigdy w życiu, zaśmiecało mi system, dużo ważyło, etc. A odpalenie kilku instancji programu, tak aby można było porobić coś jeszcze na komputerze? Zapomnij.

Dlatego zacząłem szukać czegoś lekkiego, czegoś co będę mógł szybko odpalić z terminala i od razu pracować, czegoś co będę mógł w łatwy sposób odpalić na innej maszynie, czegoś co jest darmowe, czegoś co daje mi ogromne możliwość dzięki swojej modularności, czyli czegoś co teraz nazywam Vim Python IDE. Wspomnę tylko, że najbardziej do gustu ze wszystkich edytorów jakie testowałem przypadł mi Sublime Text 2, ale i on po pewnym czasie zaczął mnie irytować. Mimo to, bardzo mocno go polecam, bo jest naprawdę dobry.

Jeżeli nie miałeś nigdy styczności z vimem, to polecam ci skorzystanie z vimtutora (taki nauczyciel vima). Odpalisz go komendą vimtutor w wierszu poleceń. Nie jest Ci to niezbędne, aby przestudiować tego posta, ale warto się z tym zapoznać albo chociaż gdzieś zapisać i poświęcić kiedyś trochę czasu na naukę.

Wszystko co jest tutaj opisane wypróbowałem jedynie na systemie Ubuntu, a moją podstawową konsolą jest gnome-terminal.

TL;DR

Jeśli nie chce ci się czytać/przepisywać/konfigurować to na końcu posta umieściłem link do repo na którym znajdziesz wszystkie pliki konfiguracyjne, z których ja korzystam i które tutaj opisałem. Zaczynamy!

Czas zacząć

Na początek kilka zrzutów ekranu, aby pokazać, że vim nie jest taki straszny (no dobra, trochę; ale tylko na początku).





Instalacja

Jeżeli masz już zainstalowanego vima (a najprawdopodobniej masz) to sprawdź czy masz ustawioną flagę xterm_clipboard (polecenie vim --version). Dzięki niej będziesz mógł w wygodny sposób korzystać ze schowka. Jeżeli nie masz to kiedyś napisałem posta co należy zrobić, aby ją uaktywnić (opis dla Ubuntu).

Jeśli nie masz zainstalowanego vima, to wykonaj polecenie sudo apt-get install vim-gnome. Dzięki temu nie będziesz musiał przejmować się niektórymi problemami, np. takimi jak brak ustawionej flagi xterm_clipboard.
I już możesz zacząć korzystać, chociaż wątpię w to, aby komukolwiek w dzisiejszych czasach odpowiadała praca w vimie bez pluginów, bo to one są tym co tak naprawdę czyni ten edytor tak wspaniałym.

Pluginy

Opiszę tutaj, krótko każdy z pluginów z których korzystam. O konfiguracji/instalacji/skrótach klawiszowych dowiesz się później, przy konfigurowaniu pliku .vimrc.
  • vim-pathogen - w wielkim skrócie, plugin do zarządzania pluginami
  • ctrlp.vim - szukanie plików, otwieranie pliku w konkretnej linii, otwieranie kilku plików, szybkie tworzenie pliku
  • python-mode - praktycznie wszystko co jest Tobie potrzebne do przyjemnego pisania kodu w Pythonie; szybki podgląd dokumentacji, wykonywanie kodu, rope autocomplete, łatwe skakanie po metodach/klasach, łatwe zaznaczanie całych metod/klas, etc.
  • nerdtree - drzewko plików (przydaje się)
  • nerdcommenter - komentowanie kodu na kilka ciekawych sposobów
  • ack.vim - używa ack (grep dla programistów) w vimie
  • powerline - w terminalu korzystam z powerline-bashtutaj o tym pisałem (uwaga, zmieniła się nazwa repo, po więcej zapraszam tutaj). Zamierzam również wykorzystać plugin powerline w bashu, ponieważ oferuje taką możliwość. Ale to temat na osobnego posta

Konfiguracja

vim-pathogen

Pierwsze co musisz zrobić to zainstalować vim-pathogen. Najlepiej wykonać dwie poniższe komendy:
mkdir -p ~/.vim/autoload ~/.vim/bundle
curl -so ~/.vim/autoload/pathogen.vim https://raw.github.com/tpope/vim-pathogen/HEAD/autoload/pathogen.vim
Od teraz będziesz mógł dodawać pluginy do katalogu ~/.vim/bundle/nazwa-pluginu/. Dodaj jeszcze w pierwszej linijce w pliku .vimrc w swoim katalogu użytkownika tą linię:
call pathogen#infect()

.vimrc

Po kolei będę wklejał bloki kodu, które należy umieścić w pliku .vimrc oraz będę je krótko opisywał do czego się przydają.

autocmd! bufwritepost .vimrc source %
Automatycznie przeładowywuje plik .vimrc.

set pastetoggle=<F2>
set clipboard=unnamed
Lepsze kopiowanie/wklejanie, jeżeli masz do wklejenia jakiś duży blok tekstu. Przechodzisz do trybu insert, wciskasz <F2> i wklejasz tekst.

set bs=2
set mouse=a
Ustawia normalną obsługę backspace oraz włącza obsługę myszki.

let mapleader = ","
Binduje <Leader> do klawisza "," . Później zobaczysz do czego może się przydać.

noremap <C-n> :nohl<CR>
vnoremap <C-n> :nohl<CR>
inoremap <C-n> :nohl<CR>
Jeżeli wyszukałeś jakąś frazę, to vim ją podkreślił, jeśli chcesz pozbyć się podświetlenia wciśnij CTRL+n.

noremap <C-Z> :update<CR>
vnoremap <C-Z> <C-C>:update<CR>
inoremap <C-Z> <C-O>:update<CR>
Szybki zapis pliku, CTRL+z.

noremap <Leader>e :quit<CR>
noremap <Leader>E :qa!<CR>
Szybkie zamknięcie pliku/plików. Już widzisz do czego przydaje się <Leader>. Po wciśnięciu ",e" vim zamknie plik nad którym aktualnie pracujesz. Jeżeli użyjesz ",E" to zostanie zamknięty cały vim. Skrótów z <Leader> możesz używać podobnie jak tych z CTRL lub wciskać jeden po drugim. Czyli w tym przypadku wciskając klawisz "e" nie musisz trzymać klawisza ",". Analogicznie będzie w kolejnych skrótach z wykorzystaniem <Leader>.

map <c-j> <c-w>j
map <c-k> <c-w>k
map <c-l> <c-w>l
map <c-h> <c-w>h
Służy do wygodniejszego poruszania się po okienkach. Zamiast wciskania CTRL+w, a później h/j/k/l, wciskasz sobie CTRL+h/j/k/l.

map <Leader>n <esc>:tabprevious<CR>
map <Leader>m <esc>:tabnext<CR>
Wygodniejsze przemieszczanie się po zakładkach. ",n" (wcześniejsza), ",m" (następna).

vnoremap < <gv
vnoremap > >gv
Wygodne przemieszczanie bloków kodu. Zaznaczasz tekst i wybierasz w którym kierunku ma być przesunięty. "<" (lewo), ">" (prawo).

autocmd ColorScheme * highlight ExtraWhitespace ctermbg=red guibg=red
au InsertLeave * match ExtraWhitespace /\s\+$/
Podświetla na czerwono niepotrzebne białe znaki (taby/spacje). Jak korzystasz z dobrodziejstw codereview to prędzej czy później będziesz tego szukał.

filetype off
filetype plugin indent on
syntax on
Włącza rozpoznawanie plików oraz podświetlanie składni.

set number
set tw=79
set nowrap
set fo-=t
set colorcolumn=80
highlight ColorColumn ctermbg=233
Pierwsza komenda wyświetla numer wiersza w którym się znajdujesz po lewej stronie. Przedostatnia i ostatnia odpowiadają za wyświetlanie się kolumny, która jest pomocna przy kodowaniu, jeżeli ustaliliście razem z zespołem jakąś konwencję. Natomiast druga, trzecia i czwarta komenda odpowiada za brak zawijania tekstu. Dodatkowo, jeżeli jest ci naprawdę potrzebne zawinięcie jakiegoś tekstu możesz go zaznaczyć i wcisnąć "gq". Program ci go zawinie do 79 kolumny i zacznie wypełniać wiersz poniżej, również do 79 kolumny i tak w kółko. Szczerze, bardzo rzadko z tego korzystam, ale przydaje się jak wrzucasz jakieś dłuższe teksy do szablonu/kodu.



set history=700
set undolevels=700
Nie trzeba tłumaczyć.

set tabstop=4
set softtabstop=4
set shiftwidth=4
set shiftround
set expandtab
W wielkim skrócie, używa tylko i wyłącznie spacji, zero tabów. Jak gdzieś użyjesz taba to ci go zamieni na cztery spacje, dziękuję.

set hlsearch
set incsearch
set ignorecase
set smartcase
Podświetla znalezioną frazę podczas szukania i rozróżnia znaki ("oink" to nie to samo co "OinK").

set nobackup
set nowritebackup
set noswapfile
Wyłącza pliki backup oraz swap. Nie są Ci do niczego potrzebne, a jak pracujesz z gitem czy mercurialem to tym bardziej.

powerline (https://github.com/Lokaltog/powerline)

Instalacja:
cd ~/.vim/bundle
git clone git://github.com/Lokaltog/powerline.git

W pliku .vimrc wklej:
set guifont=Source\ Code\ Pro\ for\ Powerline\ for\ Powerline
set laststatus=2
source ~/.vim/bundle/powerline/powerline/ext/vim/source_plugin.vim

Zmienną guifont oczywiście musisz zmienić na swoją czcionkę. Jest to potrzebne do gvima. Jeżeli z niego nie korzystasz, możesz tą linijkę usunąć albo zakomentować. Jeżeli powerline dziwnie się wyświetla musisz spatchować swoją czcionkę, jak to zrobić jest opisane tutaj. Ja osobiście korzystam z czcionki SourceCodePro (musiałem spatchować). Ustawienie zmiennej laststatus na wartość 2 zapewni wyświetlanie się linii na dole okna.

Oprócz powerline do vima, korzystam jeszcze z powerline-bash. Pisałem o nim w tym poście. Ludzie mają problemy z skonfigurowaniem tak czcionki, aby była wyświetlana poprawnie i w pluginie vima jak i w konsoli. Jeżeli będziesz używał tylko plugina powerline do vima to nie masz czym się przejmować. Jednak, jeśli zapragniesz korzystać z powerline oraz z powerline-bash to może być Ci ciężko je pogodzić. Jeżeli używasz czcionki SourceCodePro to pod koniec posta zamieściłem linki do mojego repo na githubie. Tam znajdziesz katalog .fonts. Wystarczy, że skopiujesz go do swojego katalogu domowego i w gnome-terminal ustawisz czcionkę na Source Code Pro for Powerline for Powerline.

vim-colors-solarized (https://github.com/altercation/vim-colors-solarized)

Instalacja:
cd ~./vim/bundle/
git clone https://github.com/altercation/vim-colors-solarized

Korzystam z tego colorscheme ponieważ najbardziej mi odpowiada. Ciekawym jest jeszcze wombat256mod.vim, z którego korzystałem dopóki nie natknąłem się na solarized (dark).

Do pliku .vimrc wklej to:
set t_Co=16
set background=dark
let g:solarized_termcolors=16
colorscheme solarized

Jeżeli chcesz mieć również takie kolory w terminalu (gnome-terminal) to wklej w terminalu te komendy:
gconftool-2 --set "/apps/gnome-terminal/profiles/Default/use_theme_background" --type bool false
gconftool-2 --set "/apps/gnome-terminal/profiles/Default/use_theme_colors" --type bool false
gconftool-2 --set "/apps/gnome-terminal/profiles/Default/palette" --type string "#070736364242:#D3D301010202:#858599990000:#B5B589890000:#26268B8BD2D2:#D3D336368282:#2A2AA1A19898:#EEEEE8E8D5D5:#00002B2B3636:#CBCB4B4B1616:#58586E6E7575:#65657B7B8383:#838394949696:#6C6C7171C4C4:#9393A1A1A1A1:#FDFDF6F6E3E3"
gconftool-2 --set "/apps/gnome-terminal/profiles/Default/background_color" --type string "#00002B2B3636"
gconftool-2 --set "/apps/gnome-terminal/profiles/Default/foreground_color" --type string "#65657B7B8383"

ctrlp.vim (https://github.com/kien/ctrlp.vim)

Instalacja:
cd ~/.vim/bundle
git clone https://github.com/kien/ctrlp.vim.git

Plik .vimrc
let g:ctrlp_max_height = 30
set wildignore+=*.pyc
set wildignore+=*build/*
set wildignore+=*dist/*
set wildignore+=*.egg-info/*
set wildignore+=*/coverage/*

Pierwsza komenda ustala maksymalną ilość wierszy jakie mogą się wyświetlić przy wyszukiwaniu pliku. A reszta ustawia jakie pliki/katalogi mają się Tobie nie wyświetlać podczas wyszukiwania. Aby wyświetlić CtrlP wciśnij CTRL+p (w trybie normal). Tak to mniej więcej wygląda:




Po liście, która się wyświetla poruszasz się klawiszami CTRL+j, CTRL+k, zatwierdzasz enterem albo jak chcesz w nowym tabie otworzyć CTRL+t. Dodatkowo gdy po wpisanej frazie dodasz ":<liczba>" to przeniesie Cię do zaznaczonego/zaznaczonych plików do konkretnej linijki (bardzo pomocne gdy Python wypluwa ci informacje o tym w którym pliku i w której linijce jest błąd).

A teraz, kilka najważniejszych skrótów klawiszowych odnoszących się do tego pluginu. Wszystkie oczywiście działają gdy masz otwartego CtrlP:

  • F5 - odświeżanie listy, jak usunąłeś/dodałeś jakiś plik
  • CTRL+f, CTRL+b - przełączanie się między trybami files, buffor, mru files (pliki, bufor, najczęściej otwierane pliki)
  • CTRL+d - ustawiasz czy ma szukać po ścieżce czy po pliku
  • CTRL+r - regex mode, nie raz pewnie za to podziękujesz
  • CTRL+z - gdy się poruszasz po oknie i wciśniesz ten właśnie skrót to zaznaczy/odznaczy Ci plik. Jak sobie już zaznaczyć wciskasz CTRL+o, aby je otworzyć (w tym samym oknie wszystkie pliki) albo CTRL+t, aby każdy otworzyć w osobnym tabie
  • CTRL+p, CTRL+n - wcześniejsza/następna fraza jaką wpisywałeś
  • gdy zaznaczysz kilka plików (maksymalnie cztery) i wpiszesz ":diffthis", a później wciśniesz CTRL+o to ładnie te pliki do siebie porówna i pokaże Ci gdzie się różnią
  • jak wpiszesz ścieżkę do pliku czy sam plik, który nie istnieje i użyjesz skrótu CTRL+y to CtrlP stworzy Ci ten plik

python-mode (https://github.com/klen/python-mode)

Instalacja:
cd ~/.vim/bundle
git clone https://github.com/klen/python-mode

Plik .vimrc
map <Leader>g :call RopeGotoDefinition()<CR>
let ropevim_enable_shortcuts = 1
let g:pymode_rope_goto_def_newwin = "vnew"
let g:pymode_rope_extended_complete = 1
let g:pymode_breakpoint = 0
let g:pymode_syntax = 1
let g:pymode_virtualenv = 1

Pierwsza linijka ustawia pod skrótem ",g" wywołanie RopeGotoDefinition... Jeżeli zapomniałeś czegoś na temat danego obiektu albo chcesz się dowiedzieć czegoś nowego na jego temat to wskazujesz na niego, wciskasz ",g" i przenosi cię do pliku w którym jest zaimplementowany.
Druga włącza obsługę skrótów.
W trzeciej przekazujesz w jaki sposób ma się wyświetlać okno, po znalezieniu pliku w którym obiekt jest zaimplementowany. W tym przypadku dzieli ekran pionową kreską, przykład:


Kursor miałem na stringu LoremIpsum i wcisnąłęm ",g".

Reszta w skrócie zapewnia ci wsparcie dla virtualenv, ustawia ładne podświetlanie składni oraz rozszerza podpowiadanie składni. Właśnie, czas na przydatne skróty.

  • K - wywołane na jakimś module, wyświetla okno na dole z dokumentacją danego modułu
  • ,r - odpala kod
  • CTRL+spacja - używa Rope autocomplete (poniżej jest opis jak sobie wygodnie zbindować skróty, żeby się po nim szybko poruszać)
  • [M, ]M - skakanie po metodach poprzednia/następna
  • aC - zaznaczenie całej klasy, ale! W zależności co podasz przed literą a, vim różnie się zachowa i tak oto, vaC (zaznacza całą klasę), daC albo dC (usuwa całą klasę), yaC lub yC (kopiuje całą klasę), caC albo cC (usuwa całą klasę i od razu zmienia tryb na insert)
  • iC - analogicznie jak powyżej z tym, że nie odnosi się do całej klasy, tylko do jej wnętrza
  • aM - j.w tyle, że dla metod 
  • iM - j.w tyle, że dla metod
Teraz wróć znów do pliku .vimrc i dodaj takie coś:
set completeopt=longest,menuone
function! OmniPopup(action)
    if pumvisible()
        if a:action == 'j'
            return "\<C-N>"
        elseif a:action == 'k'
            return "\<C-P>"
        endif
    endif
    return a:action
endfunction

inoremap <silent><C-j> <C-R>=OmniPopup('j')<CR>
inoremap <silent><C-k> <C-R>=OmniPopup('k')<CR>

Zapewni Ci to poruszanie się po OmniPopupie (CTRL+spacja) za pomocą CTRL+j, CTRL+k. Tak to wygląda:


nerdtree (https://github.com/scrooloose/nerdtree)

Instalacja:
" cd ~/.vim/bundle
" git clone https://github.com/scrooloose/nerdtree.git

Plik .vimrc
nmap <leader>t :NERDTree<CR>
autocmd bufenter * if (winnr("$") == 1 && exists("b:NERDTreeType") && b:NERDTreeType == "primary") | q | endif

Powyższe ustawienia bindują Ci otwieranie nerdtree pod skrótem ",t" oraz gdy zamykasz ostatnie okno w vimie i zostanie tylko nerdtree, to automatycznie się zamknie. Opis wszystkich skrótów znajdziesz tutaj. Ja najczęściej korzystam z tych:
  • o - otwarcie pliku
  • go - otwarcie pliku, ale pozostanie w oknie z nerdtree
  • t - otwarcie pliku w nowym tabie
  • T - j.w. tyle, że nie przenosi do nowego taba
  • enter, dwuklik myszką (jak to brzmi) - to samo co "o"

nerdcommenter (https://github.com/scrooloose/nerdcommenter)

Instalacja:
cd ~/.vim/bundle
git clone https://github.com/scrooloose/nerdcommenter.git

Zasada działania pluginu jest bardzo prosta. Zaznaczasz jakiś fragment kodu i wciskasz odpowiednią kombinację klawiszy, aby zakomentować kod. Tutaj, żadnej konfiguracji nie trzeba podawać. Poniżej znajdziesz skróty z których najczęściej korzystam; dołączę również obrazki, żebyś lepiej się orientował jak dany skrót działa. Za pomocą skrótu ",cu", odkomentowujesz kod. Całą dokumentację znajdziesz tutaj.

Wszystkie skróty będę odpalał z takiej pozycji:


",cc"

",c+spacja"

",cb"

ack.vim (https://github.com/mileszs/ack.vim)

Instalacja:
sudo apt-get install ack-grep
cd ~/.vim/bundle
git clone https://github.com/mileszs/ack.vim.git

O ack.vim pomyśl jak o grepie dla programistów, i tyle. W pliku .vimrc dodaj:
nmap <leader>a <Esc>:Ack!

Aby go użyć wciskasz ",a" i wpisujesz wyrażenie. Przykład dla zapytania "setUp":


Skróty klawiszowe są podobne jak w przypadku nerdtree, więc nie powinieneś mieć z tym problemu.

Koniec

To byłoby na tyle, jeżeli chodzi o vima i pythona. Jeżeli nie chce Ci się tego wszystkie wprowadzać samemu ręcznie możesz zawitać na mój profil na githubie i zajrzeć na moje repo z dotfiles do czego mocno zachęcam bo sam pewnie bym nie chciał tego wszystkiego wklepywać.

To był jeden zbiorczy post dotyczący tego jak sobie ułatwić życie w vimie, jeżeli programujesz w tym czasie w Pythonie. Mam nadzieję, że przyda Ci się to, co tutaj opisałem. Zamierzam na bieżąco opisywać jakieś ciekawe pluginy do vima. Jeżeli sam znasz coś, na co warto zwrócić uwagę to daj mi znać czy to przez maila (tomislater <taki_internetowy_znaczek> gmail.com), g+, githuba czy zostawiając tutaj komentarz.

A teraz w nagrodę za wytrwałość, śmieszny obrazek: