Przejdź do definicji funkcji w vimie

241

Jak mogę przejść do definicji funkcji za pomocą vima? Na przykład za pomocą Visual Assist mogę wpisać Alt+ gpod funkcją i otworzy to menu kontekstowe z listą plików z definicjami.

Jak mogę zrobić coś takiego w vimie?

Jon Clegg
źródło
2
Globalny GNU jest lepszy niż ctags.
Jichao,
6
@Jichao, czy możesz dać nam trochę więcej wglądu w swoje doświadczenia? Z jakimi językami gnu global działał dla Ciebie lepiej? Czy jest coś jeszcze w kontekście, który wolisz, że jestem ważny? A może używałeś go w wielu różnych scenariuszach i wydajesz się, że najczęściej / zawsze wolisz? Co lubisz w tym bardziej? Dzięki.
still_dreaming_1
@Jichao Zamieniłem twój komentarz w odpowiedź wiki społeczności. Z radością powitam twoje zmiany i dane wejściowe dla tej odpowiedzi.
still_dreaming_1

Odpowiedzi:

213

Użyj tagów. Wygeneruj plik znaczników i powiedz vimowi, gdzie używa komendy: tags. Następnie możesz po prostu przejść do definicji funkcji, używając Ctrl-]

W tym pytaniu jest więcej sztuczek i wskazówek dotyczących tagów .

Paul Tomblin
źródło
2
php jest na tyle podobny do C, że „Exuberant ctags” powinno z nim współpracować. Nie wiem, czy ma tryb python.
Paul Tomblin
5
Brak doświadczenia z Cscope. Co to jest
Paul Tomblin
10
Podobieństwo do C nie ma nic wspólnego z obsługą tagów CTag PHP. Obsługuje zarówno PHP, jak i Python. Zajrzyj na stronę ctags.sourceforge.net/languages.html, aby zobaczyć pełne wsparcie.
dane
1
jak wygenerować ctags?
dwaynemac
4
byłoby wspaniale uzyskać odniesienie do tego, gdzie najlepiej nauczyć się obsługi tych tagów.
Fzs2
137

Jeśli wszystko jest zawarte w jednym pliku, istnieje polecenie gd(jak w „definicji goto”), które zabierze Cię do pierwszego wystąpienia w pliku słowa pod kursorem, którym często jest definicja.

Scottie T.
źródło
1
co jeśli nie mam słowa pod kursorem (wolałbym je wpisać)?
Fuad Saud
@FuadSaud po prostu wyszukaj, używając/
LucasB
6
/jest prawie zawsze nieprecyzyjne, ponieważ będzie pasować do wszystkich okazji. Dowiedziałem się, że faktycznie możesz zrobić, :tag <function_name>aby przejść do definicji za pomocą ctags.
Fuad Saud
@Faud Przejdź do definicji Funkcja polega na wskazywaniu kursora identyfikatorem (w każdym IDE). Pisanie / wyszukiwanie to kolejna funkcja, mylisz je.
krwawy
101

g* wykonuje przyzwoitą pracę bez ustawiania tagów.

Oznacza to, że typ g, *(lub po prostu *- patrz poniżej), aby wyszukać słowo pod kursorem (w tym przypadku nazwa funkcji). Następnie naciśnij, naby przejść do następnego (lub Shift- w nprzypadku poprzedniego) wystąpienia.

Nie przeskakuje bezpośrednio do definicji, biorąc pod uwagę, że to polecenie po prostu wyszukuje słowo pod kursorem, ale jeśli nie chcesz obecnie zajmować się konfigurowaniem tagów, możesz przynajmniej uratować się przed koniecznością ponownego -wpisz nazwę funkcji, aby wyszukać jej definicję.

--Edycja-- Chociaż od dawna używam g *, niedawno odkryłem dwa skróty do tych skrótów!

(a) *przejdzie do następnego wystąpienia słowa pod kursorem. (Nie trzeba wpisywać gkomendy „goto” w vi).

(b) #przechodzi do poprzedniego zdarzenia w podobny sposób.

N i n nadal działają, ale „#” jest często bardzo przydatne, aby rozpocząć wyszukiwanie początkowo w odwrotnym kierunku, na przykład podczas szukania deklaracji zmiennej pod kursorem.

Brent Faust
źródło
10
Różnica między *i g*to granice słów podczas wyszukiwania. *wykonuje \<keyword\>wyszukiwanie (tak jak \bkeyword\bw regularnym wyrażeniu regularnym), podczas g*wyszukiwania keywordbez granic słów.
Nicolai S,
jeśli masz sto wystąpień funkcji w pliku, *zajmie Ci średnio 50 trafień, zanim znajdziesz definicję.
naught101
49

Użyj gdlub gDpodczas umieszczania kursora na dowolnej zmiennej w programie.

  1. gd zabierze Cię do lokalnej deklaracji.
  2. gD zabierze Cię do globalnej deklaracji.

więcej opcji nawigacji można znaleźć tutaj .

Użyj cscope do odniesienia do dużego projektu, takiego jak jądro Linuksa.

0x90
źródło
14

Jak wspomniał Paul Tomblin, musisz używać tagów . Możesz również rozważyć użycie wtyczek do wyboru odpowiedniej lub podglądu definicji funkcji pod kursorem. Bez wtyczek będziesz miał problem z wybraniem jednej z setek przeciążonych metod „doAction”, ponieważ wbudowana obsługa ctags nie uwzględnia kontekstu - tylko nazwę.

Możesz także użyć cscope i jego funkcji „znajdź globalny symbol”. Ale twój vim musi zostać skompilowany z obsługą + cscope, która nie jest domyślną opcją kompilacji.

Jeśli wiesz, że funkcja jest zdefiniowana w bieżącym pliku, możesz użyć klawiszy „gD” w trybie normalnym, aby przejść do definicji symbolu pod kursorem.

Oto najczęściej pobierana wtyczka do nawigacji
http://www.vim.org/scripts/script.php?script_id=273

Oto jeden, który napisałem, aby wybrać kontekst, przechodząc do znacznika
http://www.vim.org/scripts/script.php?script_id=2507

Mykoła Golubiew
źródło
Cześć @ mykola-golubyev, link podany w Detailed descriptionsekcji #2507skryptu jest uszkodzony. Czy możesz podać inny?
FelikZ
12

Inną popularną techniką jest umieszczanie nazwy funkcji w pierwszej kolumnie. Umożliwia to znalezienie definicji za pomocą prostego wyszukiwania.

int
main(int argc, char *argv[])
{
    ...
}

Powyższą funkcję można następnie znaleźć /^mainw pliku lub :grep -r '^main' *.cw katalogu. Dopóki kod jest odpowiednio wcięty, jedynym identyfikatorem pojawiającym się na początku wiersza jest definicja funkcji.

Oczywiście, jeśli od tego momentu nie używasz tagów , powinieneś się wstydzić! Uważam jednak, że ten standard kodowania jest również pomocnym dodatkiem.

Sędzia Maygarden
źródło
13
Zawsze zastanawiałem się, dlaczego niektórzy koderzy tak zapisują swoje podpisy!
Tarrasch
Ponadto, gdy piszesz podpisy funkcji, w tym „{” w pierwszej kolumnie, możesz szybko przechodzić do każdej funkcji, naciskając]], aby przejść do przodu w pliku i [[, aby przejść do tyłu.
BentChainRing
12

TL; DR:

Współczesnym sposobem jest użycie COC do uzupełnienia przypominającego inteligencję i jednego lub więcej serwerów językowych (LS) do przeskoczenia do definicji (i znacznie więcej). Aby uzyskać jeszcze więcej funkcji (ale nie jest to konieczne w przypadku przejścia do definicji), możesz zainstalować jeden lub więcej debuggerów i uzyskać pełną funkcjonalność IDE. Szybki start:

  1. zainstaluj wtyczkę vim, aby zarządzać wtyczkami VIM
  2. dodaj COC i (opcjonalnie) Vimspector na górze ~/.vimrc:
    call plug#begin()
    Plug 'neoclide/coc.nvim', {'branch': 'release'}
    Plug 'puremourning/vimspector'
    call plug#end()
    
  3. zadzwoń, :source $MYVIMRC | PlugInstallaby pobrać wtyczki VIM
  4. uruchom ponownie vimi zadzwoń, :CocInstall coc-marketplaceaby uzyskać łatwy dostęp do rozszerzeń COC
  5. dzwonić :CocList marketplacei wyszukiwać serwery językowe, np .:
    • wpisz, pythonaby znaleźć coc-jedi,
    • wpisz, phpaby znaleźć coc-phplsitp.
  6. (opcjonalnie) sprawdź install_gadget.py --helpdostępne debuggery, np .:
    • ./install_gadget.py --enable-python,
    • ./install_gadget.py --force-enable-phpitp.

Pełna odpowiedź:

Serwer językowy (LS) to osobna samodzielna aplikacja (jedna dla każdego języka programowania), która działa w tle i analizuje cały projekt w czasie rzeczywistym, udostępniając dodatkowe możliwości edytorowi (dowolnemu edytorowi, nie tylko vim). Dostajesz rzeczy takie jak:

  • Uzupełnianie znaczników z pamięcią przestrzeni nazw
  • przejdź do definicji
  • przeskocz do następnego / poprzedniego błędu
  • znajdź wszystkie odniesienia do obiektu
  • znajdź wszystkie implementacje interfejsu
  • zmień nazwę w całym projekcie
  • dokumentacja na temat aktywowania
  • fragmenty kodu, akcje kodu, formatowanie, przyciemnianie i wiele więcej ...

Komunikacja z serwerami językowymi odbywa się za pośrednictwem Language Server Protocol (LSP). Zarówno nvimi vim8(lub wyższy) obsługują LSP poprzez wtyczki, najpopularniejszym z nich jest Conquer of Completion (COC).

Lista aktywnie rozwijanych serwerów językowych i ich możliwości jest dostępna na stronie internetowej Lang Server . Nie wszystkie z nich są dostarczane przez rozszerzenia COC. Jeśli chcesz użyć jednego z nich, możesz samodzielnie napisać rozszerzenie COC lub ręcznie zainstalować LS i użyć kombinacji następujących wtyczek VIM jako alternatywy dla COC:

Komunikacja z debuggerami odbywa się za pośrednictwem protokołu debugowania (DAP). Najpopularniejszą wtyczką DAP dla VIM jest Vimspector .

Language Server Protocol (LSP) został stworzony przez Microsoft dla Visual Studio Code i wydany jako projekt open source z pozwoleniem MIT (standaryzowanym we współpracy z Red Hat i Codenvy). Później firma Microsoft wydała również Protokół adaptera debugowania (DAP). Każdy język obsługiwany przez VSCode jest obsługiwany w VIM.

Osobiście zalecam używanie serwerów językowych COC + dostarczonych przez rozszerzenia COC + ALE do dodatkowego przyciemniania (ale z wyłączoną obsługą LSP, aby uniknąć konfliktów z COC) + Vimspector + debuggery dostarczone przez Vimspector (zwane „gadżetami”) + następujące wtyczki VIM:

call plug#begin()
Plug 'neoclide/coc.nvim'
Plug 'dense-analysis/ale'
Plug 'puremourning/vimspector'
Plug 'scrooloose/nerdtree'
Plug 'scrooloose/nerdcommenter'
Plug 'sheerun/vim-polyglot'
Plug 'yggdroot/indentline'
Plug 'tpope/vim-surround'
Plug 'kana/vim-textobj-user'
  \| Plug 'glts/vim-textobj-comment'
Plug 'janko/vim-test'
Plug 'vim-scripts/vcscommand.vim'
Plug 'mhinz/vim-signify'
call plug#end()

Możesz google każdego, aby zobaczyć, co robią.

cprn
źródło
11

1- zainstaluj żywiołowe ctagi. Jeśli używasz systemu OSX, ten artykuł pokazuje małą sztuczkę: http://www.runtime-era.com/2012/05/exuberant-ctags-in-osx-107.html

2- Jeśli chcesz uwzględnić tylko tagi plików tylko w swoim katalogu, uruchom to polecenie w swoim katalogu:

ctags -R

Spowoduje to utworzenie pliku „tagów”.

3- Jeśli używasz Ruby i chcesz dołączyć ctags do swoich klejnotów (było to dla mnie bardzo pomocne w RubyMotion i lokalnych klejnotach, które opracowałem), wykonaj następujące czynności:

ctags --exclude=.git --exclude='*.log' -R * `bundle show --paths`

kredyt: https://coderwall.com/p/lv1qww (Uwaga: pominąłem opcję -e, która generuje tagi dla emacsa zamiast vima)

4- Dodaj następujący wiersz do ~ / .vimrc

set autochdir 
set tags+=./tags;

(Dlaczego średnik: http://vim.wikia.com/wiki/Single_tags_file_for_a_source_tree )

5- Idź do słowa, które chcesz śledzić i naciśnij ctrl + ]; jeśli chcesz wrócić, użyj ctrl+o(źródło: https://stackoverflow.com/a/53929/226255 )

Abdo
źródło
Link do wspomnianego artykułu na temat komputerów Mac jest zepsuty. Oto zaktualizowany link: runtime-era.blogspot.com/2012/05/… Najlepiej jest zainstalować ctagi za pomocą narzędzia takiego jak Homebrew
ZaydH
6

Na drugą odpowiedź Pawła: tak, ctags (szczególnie exuberant-ctags ( http://ctags.sourceforge.net/ )) są świetne. Dodałem to również do mojego vimrc, więc mogę użyć jednego pliku tagów dla całego projektu:

set tags=tags;/
David Wolever
źródło
2

Zainstaluj cscope. Działa bardzo podobnie, ctagsale mocniej. Aby przejść do definicji, zamiast Ctrl+ ]wykonaj Ctrl+ \+ g. Oczywiście możesz używać obu jednocześnie. Ale przy dużym projekcie (powiedzmy jądro Linuksa) cscope jest o wiele dalej.

Diptendu Roy Chowdhury
źródło
1

Po wygenerowaniu tagów możesz także użyć vim:

:tag <f_name>

Powyżej przeniesie Cię do definicji funkcji.

Karun
źródło