*giri-nav.txt* ------------------------------------------------------------------------ Basics: - Use and / for jumplist and `g;` and `g,` for changelist - When you do not know the code base and grokking around, use: 'ug -Q' (TUI ugrep), 'grep' inside vim, or 'file'. - Use symbol-based navigation (:h E387 include-search). To search inside files for symbols (ignoring comments) use ':il /pat'. Use `[` to jump to the occurance of the symbol shown by ':il'. `[` jumps to first definition, just like 'gd'. 'ilist' etc. search #include'd files while 'dlist' lists symbols defined under #define. (Note: `gd` also goes to definition, but it searches within the bufer and highlights all matches unlike `[`.). See the section at the end of this file. - Search buffer using ':g//' or ':g//caddexpr' (cmdline add expr to quickfix). - If you have a lot of files to edit (say log files) for some symbol, fill a buffer (see command below) with filenames and use `gf` to go through files and `` to bounce back. `:enew \| :r !find . -type f -name "*.log"` ------------------------------------------------------------------------ matchit plugin In Vim, as in plain vi, the percent key, |%|, jumps the cursor from a brace, bracket, or paren to its match. This can be configured with the 'matchpairs' option. So you can jump from 'if' to 'else' to 'endif' etc. Keymaps: %, g%, [%, ]%. See |matchit|. ------------------------------------------------------------------------ Keymap help *gkeymap-window-mgmt* Window :wincmd :[count]winc[md] {arg} Like executing CTRL-W [count] {arg}. Example: > :wincmd j s: "Split window", v: "Split window vertically", w: "Switch windows", q: "Quit a window", o: "Close all other windows", T: "Break out into a new tab", x: "Swap current with next", "-": "Decrease height", "+": "Increase height", "<": "Decrease width", ">": "Increase width", "|": "Max out the width", "_": "Max out the height", "=": "Equally high and wide", h: "Go to the left window", l: "Go to the right window", k: "Go to the up window", j: "Go to the down window", ------------------------------------------------------------------------ Folds *giri-folds* *folds-giri* With `foldnestmax` set to 1, you can use lower-case version of the following commands. zm is same as zM, etc. zR <- open all folds ('R'educe fold by opening more folds) zM <- close all folds ('M'ore folding) zA: "Toggle all folds under cursor", zO: "Open all folds under cursor", zC: "Close all folds under cursor", The command zc will close a fold (if the cursor is in an open fold), and zo will open a fold (if the cursor is in a closed fold). It's easier to just use 'za' which will toggle the current fold (close it if it was open, or open it if it was closed). The commands zc (close), zo (open), and za (toggle) operate on one level of folding, at the cursor. The commands zC, zO and 'zA' are similar, but operate on all folding levels (for example, the cursor line may be in an open fold, which is inside another open fold; typing zC would close all folds at the cursor). The command zr reduces folding by opening one more level of folds throughout the whole buffer (the cursor position is not relevant). Use 'zR' to open all folds. The command zm gives more folding by closing one more level of folds throughout the whole buffer. Use 'zM' to close all folds. z key <- letter z looks like folded paper from the side m/M = more folding (under cursor / all) r/R = reduce folding c = close o = open [z, ]z to hop through folds zo: "Open fold under cursor", zO: "Open all folds under cursor", zc: "Close fold under cursor", zC: "Close all folds under cursor", za: "Toggle fold under cursor", zA: "Toggle all folds under cursor", zM: "Close all folds", zR: "Open all folds", zm: "Fold more", zr: "Fold less", zx: "Update folds", zz: "Center this line", zt: "Top this line", z"": "Top this line, cursor in 1st non-blank col", zb: "Bottom this line", zg: "Add word to spell list", zw: "Mark word as bad/misspelling", ze: "Right this line", zs: "Left this line", zH: "Half screen to the left", zL: "Half screen to the right", zi: "Toggle folding", z["="]: "Spelling suggestions", ------------------------------------------------------------------------ `g` key *giri-g-keymap* "g;": "cycle thru recent changes (oldest first)", "g,": "reverse direction of above", "gf": "Go to file under cursor", "gx": "Open the file under cursor with system app", "gi": "Move to the last insertion and INSERT", "gv": "Switch to VISUAL using last selection", "gn": "Search forwards and select", "gN": "Search backwards and select", "g%": "Cycle backwards through results", ------------------------------------------------------------------------ Navigation tricks *giri-[-keymap* Navigation [ and ] *gkeymap-sq-brkt* "[{": "Previous {", "[(": "Previous (", "[": "Previous <", "[m": "Previous method start", "[M": "Previous method end", "[%": "Previous unmatched group", "[s": "Previous misspelled word", "]{": "Next {", "](": "Next (", "]": "Next <", "]m": "Next method start", "]M": "Next method end", "]%": "Next unmatched group", "]s": "Next misspelled word", "H": "Home line of window (top)", "M": "Middle line of window", "L": "Last line of window", "]i": "Search symbol in include file (forward)", "[i": "Search symbol in include file (backward", "]d": "Search macro (#define) symbols", "[d": "Search macro (#define) symbols", Bram says `[` will jump to symbol definition. It does look for included files and other files in dir. `gd` also goes to definition, but it searches within the file and highlights all matches unlike `[`. ------------------------------------------------------------------------ To start long completion~ |ins-completion| |complete-functions| To start long completion chain, start by |ins-completion-menu| explains c-n c-p México M^n^p^x^p^x^p ^n starts completion, ^p takes back the characters upto M, ^c^p finish next two fragments ------------------------------------------------------------------------------ Indenting a block in C~ In Visual mode "=" indents the selected lines. A useful text object is "a{". This selects the current {} block. Thus, to re-indent the code block the cursor is in: > =a{ ------------------------------------------------------------------------------ *29.3* Moving through a program~ *giri-moving-through-program* Since a program is structured, Vim can recognize items in it. Specific commands can be used to move around. C programs often contain constructs like this: #ifdef USE_POPEN ~ fd = popen("ls", "r") ~ #else ~ fd = fopen("tmp", "w") ~ #endif ~ But then much longer, and possibly nested. Position the cursor on the "#ifdef" and press %. Vim will jump to the "#else". Pressing % again takes you to the "#endif". Another % takes you to the "#ifdef" again. When you are somewhere inside a "#if" - "#endif", you can jump to the start of it with: > [# If you are not after a "#if" or "#ifdef" Vim will beep. To jump forward to the next "#else" or "#endif" use: > ]# MOVING IN CODE BLOCKS An overview: function(int a) +-> { | if (a) | +-> { [[ | | for (;;) --+ | | +-> { | | [{ | | foo(32); | --+ | | [{ | if (bar(a)) --+ | ]} | +-- | +-- break; | ]} | | | } <-+ | | ][ +-- foobar(a) | | } <-+ | } <-+ The next level of {} is for a method. When somewhere inside a class use "[m" to find the previous start of a method. "]m" finds the next start of a method. int func1(void) { return 1; +----------> } | [] | int func2(void) | +-> { | [[ | if (flag) start +-- +-- return flag; | ][ | return 2; | +-> } ]] | | int func3(void) +----------> { return 3; } Don't forget you can also use "%" to move between matching (), {} and []. That also works when they are many lines apart. MOVING IN BRACES The "[(" and "])" commands work similar to "[{" and "]}", except that they work on () pairs instead of {} pairs. > [( < <-------------------------------- <------- if (a == b && (c == d || (e > f)) && x > y) ~ --------------> --------------------------------> > ]) MOVING IN COMMENTS To move back to the start of a comment use "[/". Move forward to the end of a comment with "]/". This only works for /* - */ comments. *29.4* Finding global identifiers You are editing a C program and wonder if a variable is declared as "int" or "unsigned". A quick way to find this is with the "[I" command. Suppose the cursor is on the word "column". Type: > [I Vim will list the matching lines it can find. Not only in the current file, but also in all included files (and files included in them, etc.). The result looks like this: structs.h ~ 1: 29 unsigned column; /* column number */ ~ The advantage over using tags or the preview window is that included files are searched. In most cases this results in the right declaration to be found. LOCATING INCLUDED FILES Vim will find included files in the places specified with the 'path' option. If a directory is missing, some include files will not be found. You can discover this with this command: > :checkpath It will list the include files that could not be found. Also files included by the files that could be found. An example of the output: --- Included files not found in path --- ~ ~ vim.h --> ~ ~ ~ The "io.h" file is included by the current file and can't be found. "vim.h" can be found, thus ":checkpath" goes into this file and checks what it includes. The "functions.h" and "clib/exec_protos.h" files, included by "vim.h" are not found. Note: Vim is not a compiler. It does not recognize "#ifdef" statements. This means every "#include" statement is used, also when it comes after "#if NEVER". To fix the files that could not be found, add a directory to the 'path' option. A good place to find out about this is the Makefile. Look out for lines that contain "-I" items, like "-I/usr/local/X11". To add this directory use: > :set path+=/usr/local/X11 When there are many subdirectories, you can use the "*" wildcard. Example: > :set path+=/usr/*/include When working on a project with a whole nested tree of included files, the "**" items is useful. This will search down in all subdirectories. Example: > :set path+=/projects/invent/**/include If you want to see which included files are actually found, use this command: > :checkpath! JUMPING TO A MATCH "[I" produces a list with only one line of text per line. When you want to have a closer look at the first item, you can jump to that line with the command: > [ The list that "[I" produces has a number at the start of each line. When you want to jump to another item than the first one, type the number first: > 3[ Will jump to the third item in the list. Remember that you can use CTRL-O to jump back to where you started from. RELATED COMMANDS [i only lists the first match ]I only lists items below the cursor ]i only lists the first item below the cursor FINDING DEFINED IDENTIFIERS The "[I" command finds any identifier. To find only macros, defined with "#define" use: > [D Again, this searches in included files. The 'define' option specifies what a line looks like that defines the items for "[D". You could change it to make it work with other languages than C or C++. The commands related to "[D" are: [d only lists the first match ]D only lists items below the cursor ]d only lists the first item below the cursor *29.5* Finding local identifiers The "[I" command searches included files. To search in the current file only, and jump to the first place where the word under the cursor is used: > gD Hint: Goto Definition. This command is very useful to find a variable or function that was declared locally ("static", in C terms). Example (cursor on "counter"): +-> static int counter = 0; | | int get_counter(void) gD | { | ++counter; +-- return counter; } To restrict the search even further, and look only in the current function, use this command: > gd This will go back to the start of the current function and find the first occurrence of the word under the cursor. Actually, it searches backwards to an empty line above a "{" in the first column. From there it searches forward for the identifier. Example (cursor on "idx"): int find_entry(char *name) { +-> int idx; | gd | for (idx = 0; idx < table_len; ++idx) | if (strcmp(table[idx].name, name) == 0) +-- return idx; } ------------------------------------------------------------------------------- https://vimways.org/2018/death-by-a-thousand-files/ # To make show popup (just like ) # set wildcharm= nnoremap e :e **/*| # type 'foo' # :find is same as :edit except you can specify 'path' to tell where to search # see :echo &path set path-=/usr/include set path+=** set path-= # :find foo nnoremap ff :find # NOTE: use 'gf' on import statements in java to jump to that file # :checkpath! if executable("rg") # set grepprg=ag\ --nogroup\ --nocolor\ --ignore-case\ --column set grepprg=rg\ --vimgrep\ --no-heading\ --smart-case set grepformat=%f:%l:%c:%m,%f:%l:%m endif nnoremap g :silent grep # nnoremap g :silent lgrep # https://www.vi-improved.org/recommendations/ # nnoremap a :argadd =fnameescape(expand('%:p:h'))/*| # add files, like **/*.md # nnoremap j :tjump / # nnoremap m :make # Convince java that 'class' is a macro like C's #define autocmd FileType java setlocal define=^\\s*class autocmd FileType python,vim setlocal define=^\\s*def # symbol-based navigation (i = include files, d = #define/macro ) # ----------------------- # :ilist :dlist and tags # :ijump Template " jump to first match of 'Template' in includes # :ij /Tem " jump to first match of pattern 'Tem' in includes # Say: import {escapeForHTML} from './helpers'; # :isearch /esca " explains what escapeForHTML does (or '[i' if under cursor) # NOTE: ilist is for symbols within visible context (#included or imported files) # dlist looks for 'macros' # #'define' commands have the same syntax as their 'include' counterparts. You just have to replace i with d: # Include Define # :ijump (:ij) :djump (:dj) # :isearch :dsearch # :ilist :dlist (:[id]list / <- lists everything) # [ [ # [I [D # ]i ]d nnoremap fi :ilist| # search for pattern (for symbols), :il (girish: above will search all files for variable, fn name etc.) nnoremap fd :dlist/| # :dli (girish: above will list all #define when you do / and search in all files) #--------------------- # TAG JUMPING: #--------------------- # Bram (in video): ctags will help you go to definition, but if you # want to list all usages of a function you need cscope # # Create 'tags' file' (install ctags) command! MakeTags !ctags -R . # ctrl-] to jump to tag under cursor # g ctrl-] for ambiguous tags (get a list of all instances of tag) # ctrl-t to jump back up the tag stack # :tjump :tselect Macros in command mode # Macros, work like abbrevs, :h wcm <- Use and for history # set wcm= # cnoremap ee getcmdtype() == ':' ? 'e ~/.zshenv' : 'ev' # cnoremap ez getcmdtype() == ':' ? 'e ~/.zshrc' : 'ez' # cnoremap pu getcmdtype() == ':' ? 'PlugUpdate' : 'pu' BUILD INTEGRATION: # set makeprg=bundle\ exec\ rspec\ -f # run :make # :cl to list errors # :cn and :cp to navigate errors # :cc# to jump to numbered error ---------------------------------------- vim:tw=78:ts=8:ft=help:norl:set modifiable noreadonly: