Zur Funktionsdefinition in vim springen

241

Wie kann ich mit vim zu einer Funktionsdefinition springen? Mit Visual Assist kann ich beispielsweise Alt+ gunter einer Funktion eingeben und ein Kontextmenü mit den Dateien mit Definitionen öffnen.

Wie kann ich so etwas in vim machen?

Jon Clegg
quelle
2
gnu global ist besser als ctags.
Jichao
6
@Jichao, kannst du uns etwas mehr Einblick in deine Erfahrungen geben? Mit welchen Sprachen hat gnu global für Sie besser funktioniert? Gibt es noch etwas an dem Kontext, den Sie bevorzugt haben, weil ich wichtig bin? Oder haben Sie es in vielen verschiedenen Szenarien verwendet und scheinen es meistens / immer zu bevorzugen? Was magst du besser daran? Vielen Dank.
still_dreaming_1
@Jichao Ich habe deinen Kommentar in eine Community-Wiki-Antwort verwandelt. Ich würde mich über Ihre Änderungen und Beiträge zu dieser Antwort freuen.
still_dreaming_1

Antworten:

213

Verwenden Sie ctags. Generieren Sie eine Tags-Datei und teilen Sie vim mit dem Befehl: tags mit, wo sie sich befindet. Dann können Sie einfach mit Ctrl- zur Funktionsdefinition springen.]

In dieser Frage finden Sie weitere Tricks und Tipps für Tags .

Paul Tomblin
quelle
2
PHP ist C-ähnlich genug, dass "Exuberant ctags" damit funktionieren sollten. Ich weiß nicht, ob es einen Python-Modus gibt.
Paul Tomblin
5
Keine Erfahrung mit Cscope. Was ist, ist?
Paul Tomblin
10
Die Ähnlichkeit mit C hat nichts mit CTags zu tun, die PHP unterstützen. Es unterstützt sowohl PHP als auch Python. Unter ctags.sourceforge.net/languages.html finden Sie die vollständige Unterstützung.
Daten
1
Wie generiere ich ctags?
Dwaynemac
4
Es wäre großartig, einen Hinweis darauf zu erhalten, wo es am besten ist, zu lernen, wie man diese ctags bedient.
Fzs2
137

Wenn alles in einer Datei enthalten ist, gibt es den Befehl gd(wie in 'goto definition'), der Sie zum ersten Vorkommen in der Datei des Wortes unter dem Cursor führt, was häufig die Definition ist.

Scottie T.
quelle
1
Was ist, wenn ich das Wort nicht unter dem Cursor habe (ich würde es lieber eingeben)?
Fuad Saud
@ FuadSaud suchen Sie einfach mit/
LucasB
6
/ist fast immer nicht präzise, ​​da es allen Vorkommen entspricht. Ich habe herausgefunden, dass Sie tatsächlich :tag <function_name>über ctags zur Definition springen können.
Fuad Saud
Die Funktion @Faud Jump To Definition basiert auf dem Zeigen eines Bezeichners mit einem Cursor (in jeder IDE). Tippen / Suchen ist eine weitere Funktion, Sie verwirren sie.
blutiger
101

g* macht einen anständigen Job, ohne dass ctags eingerichtet werden.

Das heißt, Typ g, *(oder auch nur *- siehe unten) für das Wort unter dem Cursor (in diesem Fall der Name der Funktion) zu suchen. Drücken Sie dann n, um zum nächsten (oder Shift- nfür das vorherige) Ereignis zu gelangen.

Es springt nicht direkt zur Definition, da dieser Befehl nur nach dem Wort unter dem Cursor sucht. Wenn Sie sich jedoch im Moment nicht mit dem Einrichten von ctags befassen möchten, können Sie sich zumindest ersparen, dass Sie es erneut tun müssen Geben Sie den Funktionsnamen ein, um nach seiner Definition zu suchen.

--Edit-- Obwohl ich g * schon lange benutze, habe ich kürzlich zwei Verknüpfungen für diese Verknüpfungen entdeckt!

(a) *springt zum nächsten Vorkommen des Wortes unter dem Cursor. (Sie müssen den gBefehl 'goto' nicht in vi eingeben.)

(b) #geht in ähnlicher Weise zum vorherigen Vorkommen.

N und n funktionieren immer noch, aber '#' ist oft sehr nützlich, um die Suche zunächst in umgekehrter Richtung zu starten, beispielsweise wenn nach der Deklaration einer Variablen unter dem Cursor gesucht wird.

Brent Faust
quelle
10
Der Unterschied zwischen *und g*ist Wortgrenzen bei der Suche. *führt eine \<keyword\>Suche durch (wie \bkeyword\bim regulären regulären Ausdruck), während g*nach keywordohne Wortgrenzen gesucht wird.
Nicolai S
Wenn Sie hundert Vorkommen einer Funktion in einer Datei haben, werden *Sie durchschnittlich 50 Treffer erhalten, bevor Sie die Definition finden.
naught101
49

Verwenden Sie gdoder gDwährend Sie den Cursor auf eine beliebige Variable in Ihrem Programm setzen.

  1. gd bringt Sie zur lokalen Erklärung.
  2. gD bringt Sie zur globalen Deklaration.

Weitere Navigationsoptionen finden Sie hier .

Verwenden Sie cscope, um auf große Projekte wie den Linux-Kernel zu verweisen.

0x90
quelle
14

Wie Paul Tomblin erwähnt hat, müssen Sie ctags verwenden . Sie können auch Plugins verwenden , um ein geeignetes auszuwählen oder eine Vorschau der Definition der Funktion unter dem Cursor anzuzeigen. Ohne Plugins werden Sie Kopfschmerzen haben, wenn Sie versuchen, eine der Hunderte überladenen 'doAction'-Methoden auszuwählen, da die integrierte ctags-Unterstützung den Kontext nicht berücksichtigt - nur einen Namen.

Sie können auch cscope und die Funktion "Globales Symbol suchen" verwenden. Ihr vim muss jedoch mit + cscope-Unterstützung kompiliert werden, was nicht standardmäßig eine Build-Option ist.

Wenn Sie wissen, dass die Funktion in der aktuellen Datei definiert ist, können Sie im normalen Modus 'gD'-Tastenanschläge verwenden, um zur Definition des Symbols unter dem Cursor zu springen.

Hier ist das am häufigsten heruntergeladene Plugin für die Navigation:
http://www.vim.org/scripts/script.php?script_id=273

Hier ist eine, die ich geschrieben habe, um den Kontext auszuwählen, während ich zum Tag http://www.vim.org/scripts/script.php?script_id=2507 springe

Mykola Golubyev
quelle
Hallo @ mykola-golubyev, der Link, den Sie im Detailed descriptionAbschnitt des #2507Skripts angegeben haben, ist defekt. Können Sie bitte einen anderen zur Verfügung stellen?
FelikZ
12

Eine andere übliche Technik besteht darin, den Funktionsnamen in die erste Spalte zu setzen. Dadurch kann die Definition mit einer einfachen Suche gefunden werden.

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

Die obige Funktion kann dann /^maininnerhalb der Datei oder :grep -r '^main' *.cin einem Verzeichnis gefunden werden. Solange der Code richtig eingerückt ist, befindet sich der Bezeichner nur am Anfang einer Zeile in der Funktionsdefinition.

Wenn Sie ab diesem Zeitpunkt keine ctags mehr verwenden, sollten Sie sich natürlich schämen! Ich finde diesen Codierungsstandard jedoch auch eine hilfreiche Ergänzung.

Richter Maygarden
quelle
13
Ich habe mich immer gefragt, warum manche Programmierer ihre Unterschriften so schreiben!
Tarrasch
Wenn Sie Ihre Funktionssignaturen schreiben, einschließlich '{' in der ersten Spalte, können Sie schnell zu jeder Funktion wechseln, indem Sie]] drücken, um in der Datei vorwärts und [[rückwärts zu gehen.
BentChainRing
12

TL; DR:

Der moderne Weg besteht darin, COC für die Intellisense-ähnliche Vervollständigung und einen oder mehrere Sprachserver (LS) für den Sprung zur Definition (und viel mehr) zu verwenden. Für noch mehr Funktionen (die jedoch nicht für die Definition benötigt werden) können Sie einen oder mehrere Debugger installieren und eine umfassende IDE-Erfahrung erzielen. Schnellstart:

  1. Installieren Sie vim-plug , um Ihre VIM-Plug-Ins zu verwalten
  2. Fügen Sie COC und (optional) Vimspector oben hinzu ~/.vimrc:
    call plug#begin()
    Plug 'neoclide/coc.nvim', {'branch': 'release'}
    Plug 'puremourning/vimspector'
    call plug#end()
    
  3. Rufen Sie :source $MYVIMRC | PlugInstallan, um VIM-Plug-Ins herunterzuladen
  4. Starten Sie neu vimund rufen Sie :CocInstall coc-marketplacean, um einfachen Zugriff auf COC-Erweiterungen zu erhalten
  5. Rufen Sie an :CocList marketplaceund suchen Sie nach Sprachservern, z.
    • Typ pythonzu finden coc-jedi,
    • Typ phpzu finden coc-phpls, etc.
  6. (optional) siehe install_gadget.py --helpverfügbare Debugger, z.
    • ./install_gadget.py --enable-python,
    • ./install_gadget.py --force-enable-php, etc.

Vollständige Antwort:

Language Server (LS) ist eine separate eigenständige Anwendung (eine für jede Programmiersprache), die im Hintergrund ausgeführt wird und Ihr gesamtes Projekt in Echtzeit analysiert und Ihrem Editor (nicht nur jedem Editor vim) zusätzliche Funktionen zur Verfügung stellt . Sie erhalten Dinge wie:

  • Namespace-fähige Tag-Vervollständigung
  • Zur Definition springen
  • zum nächsten / vorherigen Fehler springen
  • Hier finden Sie alle Verweise auf ein Objekt
  • Hier finden Sie alle Schnittstellenimplementierungen
  • Umbenennen über ein ganzes Projekt
  • Dokumentation zum Schweben
  • Schnipsel, Code-Aktionen, Formatierung, Flusen und mehr ...

Die Kommunikation mit Sprachservern erfolgt über das Language Server Protocol (LSP). Beide nvimund vim8(oder höher) unterstützen LSP über Plug-Ins, am beliebtesten ist Conquer of Completion (COC).

Eine Liste der aktiv entwickelten Sprachserver und ihrer Funktionen finden Sie auf der Lang Server- Website. Nicht alle davon werden von COC-Erweiterungen bereitgestellt. Wenn Sie eine davon verwenden möchten, können Sie entweder selbst eine COC-Erweiterung schreiben oder LS manuell installieren und die Kombination der folgenden VIM-Plug-Ins als Alternative zu COC verwenden:

Die Kommunikation mit Debuggern erfolgt über das Debug Adapter Protocol (DAP). Das beliebteste DAP-Plug-In für VIM ist Vimspector .

Das Language Server Protocol (LSP) wurde von Microsoft für Visual Studio Code erstellt und als Open Source-Projekt mit einer zulässigen MIT-Lizenz (standardisiert durch die Zusammenarbeit mit Red Hat und Codenvy) veröffentlicht. Später veröffentlichte Microsoft auch das Debug Adapter Protocol (DAP). Jede von VSCode unterstützte Sprache wird in VIM unterstützt.

Ich persönlich empfehle die Verwendung von COC + Sprachservern, die von COC-Erweiterungen bereitgestellt werden + ALE für zusätzliches Flusen (jedoch mit deaktivierter LSP-Unterstützung, um Konflikte mit COC zu vermeiden) + Vimspector + Debugger, die von Vimspector bereitgestellt werden (als "Gadgets" bezeichnet) + folgende VIM-Plug-Ins:

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()

Sie können jeden googeln, um zu sehen, was er tut.

cprn
quelle
11

1- Installieren Sie üppige ctags. Wenn Sie osx verwenden, zeigt dieser Artikel einen kleinen Trick: http://www.runtime-era.com/2012/05/exuberant-ctags-in-osx-107.html

2- Wenn Sie nur die ctags für die Dateien in Ihr Verzeichnis aufnehmen möchten, führen Sie diesen Befehl in Ihrem Verzeichnis aus:

ctags -R

Dadurch wird eine "Tags" -Datei für Sie erstellt.

3- Wenn Sie Ruby verwenden und die ctags für Ihre Edelsteine ​​einfügen möchten (dies war für mich mit RubyMotion und den von mir entwickelten lokalen Edelsteinen sehr hilfreich), gehen Sie wie folgt vor:

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

Bildnachweis: https://coderwall.com/p/lv1qww (Beachten Sie, dass ich die Option -e weggelassen habe, mit der Tags für Emacs anstelle von vim generiert werden.)

4- Fügen Sie Ihrem ~ / .vimrc die folgende Zeile hinzu

set autochdir 
set tags+=./tags;

(Warum das Semikolon: http://vim.wikia.com/wiki/Single_tags_file_for_a_source_tree )

5- Gehen Sie zu dem Wort, dem Sie folgen möchten, und drücken Sie ctrl + ]; Wenn Sie zurückkehren möchten, verwenden Sie ctrl+o(Quelle: https://stackoverflow.com/a/53929/226255 )

Abdo
quelle
Der Link zum genannten Mac-Artikel ist defekt. Hier ist der aktualisierte Link: runtime-era.blogspot.com/2012/05/… Am besten installieren Sie ctags mit einem Tool wie Homebrew
ZaydH
6

Zur zweiten Antwort von Paul: Ja, ctags (insbesondere üppige ctags ( http://ctags.sourceforge.net/ )) sind großartig. Ich habe dies auch zu meinem vimrc hinzugefügt, damit ich eine Tag-Datei für ein gesamtes Projekt verwenden kann:

set tags=tags;/
David Wolever
quelle
2

Installieren cscope. Es funktioniert sehr ähnlich, ctagsaber leistungsfähiger. Um zur Definition zu gelangen , tun Sie anstelle von Ctrl+ + + . Natürlich können Sie beide gleichzeitig verwenden. Aber mit einem großen Projekt (sagen wir Linux-Kernel) ist cscope meilenweit voraus.]Ctrl\g

Diptendu Roy Chowdhury
quelle
1

Nach dem Generieren von ctags können Sie in vim auch Folgendes verwenden:

:tag <f_name>

Oben gelangen Sie zur Funktionsdefinition.

Karun
quelle