Edit Help file outside doc directory causes tags not to work when copying in - vim

I've created a help file under $VIM\vimfiles\doc. After nearly deleting it I wanted to edit it elsewhere and then copy it to the doc directory and then regenerate the tags.
The tags are generated , I can see them in the tagfile, but the file that I copy in, unique name, when I do :h sfcontents for eg and then ctrl-] on a tag I get the error "e426 tag not found"
If I edit the file in the $VIM\vimfiles\doc directory and then run either :Helptags or :helptags $VIM\vimfiles\doc the tag jump works
I can't attach a file but the help file looks something like
vim: filetype=help foldmethod=indent foldclose=all modifiable noreadonly
Table of Contents *sfcontents*
*sfsearch* - Search specific commands help
|count-matches-of-pattern|
|match-specific-column|
...
==============================================================================
count-matches-of-pattern
*count-matches-of-pattern*
:%s/pattern//gn
counts the number of the matches in a file eg count the number of spaces
not at the beginning of a line
:%s/[^ ]\+//gn
==============================================================================
*match-specific-column*
c=column l=line v=virtual column, ie ignore tabs and special chars
/\%5cx will match all occurrences of x at column 5.
/\%>5vx will match all occurrences of x after character 5. If there is a
tab character between poition 1 and position 5 the /\%5>v. against the
following line with a tab at position 4 will return the number 4
123 45
/\%>4cx\%<7cx will match all occurrences of x after column 4 and before
column 7
Or use |YankMatchesToReg| eg YankMatchesToReg /\%265v./x which copies
column 265 to register x across the whole file
==============================================================================
...
vim:tw=88:ts=4:ft=help:norl
I've ended up doing the archive out of the vim directory with the following;
nmap <leader>c :sp C:\Progra~2\vim\vimfiles\doc\commands.txt<cr>
nmap <leader>co :call BackupCommands()<cr>
function! BackupCommands()
exec "silent! !copy C:\\Progra~2\\Vim\\vimfiles\\doc\\commands.txt
C:\\Progra~2\\vimutils\\vimtips\\commands_back.txt"
exec "helptags C:\\Progra~2\\Vim\\vimfiles\\doc\\"
endfunction
I'd prefer to copy from the archive to the doc directory rather than the other way round. Any suggestions.

Straight from Vim's help files (:h write-local-help):
The first line is actually the only one for which the format matters. It will
be extracted from the help file to be put in the "LOCAL ADDITIONS:" section of
help.txt |local-additions|. The first "*" must be in the first column of the
first line. After adding your help file do ":help" and check that the entries
line up nicely.
Short: You're missing *sfsearch.txt* as first characters in your file!
Vim wont add to |local-additions|, therefore wont be searched, assuming your tags file was generated correctly. You can verify that by opening the tags file in the /doc directory and finding your tags there manually. There should be a tags file in each correctly helptagged /doc directory (:helptags <doc-dir>).

IMO, fear of "nearly deleting" a file is not a proper reason for editing in another location and copying back and forth. In fact, you've now introduced another risk of accidentally losing file contents via a wrong copy command.
Instead, use proper version control (Git, Mercurial, etc.), or, if that's too heavyweight, you can try my writebackup plugin, a pure Vimscript implementation. With the companion writebackupToAdjacentDir plugin, you can even backup to other directories.
That said, tag jumping should work even with your copy regime, provided that you run :helptags $VIM\vimfiles\doc after copying your help file to that exact location.

Related

Make VIM to consider current folder the root

I already know how to quit Vim, now I'm wondering is it possible anyhow to force Vim search '/somedir/file.js' in current directory when you press gf, as if it were './somedir/file.js'?
UPD: There's question how to set path in general, but it doesn't help to make /myfolder/ pointed to some certain folder I want. /myfolder/ is always absolute path to the root of current volume.
Vim counts filenames beginning with / as file system root always, as
you observed. If that wasn't the case, of if 'isf' (the option that
controls what is considered file name) accepted a regex, this would be
easier to solve. But if you remove / from 'isf' then no slashes are
considered part of a file name anymore.
The only solution to this I can think of is using the visual mode for
gf. As you may know, if you have text selected visually and use gf
then the visual selection will be considered, instead of the 'isf'
match. Then all we need to do is to visually select the file name under
cursor excluding a possible leading /. This can be solved in a map, if
you don't mind messing your previous search:
nnoremap <silent> gf :let #/ = substitute(expand('<cfile>'), '^/', '', '')
\ <bar>normal gngf<cr>
This overwrites your gf to set the search to the filename under cursor
(expand()), minus leading slash if any (substitute()) and then run
the normal commands gn which selects the match and finally the
original gf.
If you want to save your previous search and restore, you can easily
create a function to wrap this all. Note that I also wrote this is two
lines just because I'm a declared enemy of long lines. But if you just
want to test it remove the \ and write in a single line.
Now your gf will interpret /file as file. Thus if you're on the
correcty directory this will work. If you need to search in a different
directory, the option you're looking for is 'path', or 'pa' for
short. You can give a list of directories to search. Much like Unix
shell's $PATH. Separated by commas. From the help (be sure to read the
rest yourself, with :h 'pa):
This is a list of directories which will be searched when using the
gf, [f, ]f, ^Wf, :find, :sfind, :tabfind and other
commands, provided that the file being searched for has a relative
path (not starting with "/", "./" or "../"). The directories in the
'path' option may be relative or absolute.
In conclusion, to use this in your project, set your 'path' if needed
as you wish and enable this map. Or run it all automatically in a
:autocmd or something similar. You aren't changing the root of the
project as you initially suggested, but you're kind of emulating this by
including the desired directory in 'path' and then forcing gf to
ignore the leading /.

VIM open c++ header file in vertical split by combining three commands

I have indexed my c++ codebase with ctags, I can open a header file as follows:
:tag myfile.h
(It doesn't matter where myfile.h is located, as long as it is inside the indexed codebase it will open correctly in vim)
When I'm editing a c++ file, I can get the header filename as follows:
:e%<.h
e.g. when editing myfile.cpp, executing this command will display myfile.h on the command line.
A file can be opened in vertical split, by issuing:
:vs <myfile>
Now what I want to accomplish, is to have 1 command or function which I can use to open a header file of the corresponding c++ file that I'm currently editing in vertical split. Hence basically I want to combine the 3 above commands as if I would be doing a Unix pipe, e.g.:
:vs tag | e%<.h
" :vs to open file in vertical split
" :tag to find tag
" :e%<.h to get header filename
Obviously the Unix pipe doesn't work on vim, alternatively I've tried to write a function at which I assign the result of a command to a variable, e.g.
headerFileName = :e%<.h
Which apparently is not the correct way of doing this, I'm a bit lost here so I hope somebody can provide some help.
There exist several plugins that already do this (without needing a ctags database BTW).
For instance, with alternate (aka a.vim), you just have to type :VS from the header file or the source file to open the other one in a vertically split window.
Note that alternate have an option to tell where to find the other file (same directory, substitute on directory name, ...)
Otherwise, I suspect you are looking for expand() and :exe. If you write a function it may be
function! s:whatever() abort
let crt = expand('%:t:r')
vnew
exe 'tag '.crt.'.h'
endfunction
command! whatever call s:whatever()

.vimrc TAGS command errors

I use etags with vim on linux for source(*.c, *.h) code browsing. I have created a TAGS file bu giving command :
etags --members *.c *.h
TAGS file gets created but when I start browsing say one of the source files named 1.c which has a C structure variable defined and used in one of its function definitions(The structure name is a typedef in some other 1.h file). I open the file 1.c in vim and then I do CTRL - ] by placing cursor on that struct type, etags does not browse to the header file 1.h which has declaration of this structure.
This only happens when i have below line in my .vimrc, when i comment below two lines, etags based source browsing works fine.
set TAGS=./TAGS;$HOME
set tags=./tags;$HOME
I am trying to tell vim where to locate the TAGS file. starting from current folder till my home dir. What is incorrect here?
What is the correct syntax for above command?
Also does ctags/etags browsing with vim, show from where all a given function is called from?
If yes, what is the command to see that?
Locating tags file
Vim's settings are case-sensitive so set TAGS= is invalid. You must use set tags= in lowercase.
Vim will stop at the first match so you can't really expect it to search for a tag in tags and TAGS. These files can be searched in turn with:
set tags=./tags,./TAGS;$HOME " 1. tags, 2. TAGS, 3.… until $HOME
Also, search is not performed by etags, it's done by Vim itself.
Jumping to function calls
No, ctags and etags only index declarations. To jump to usage you'll need cscope

Ignore one "misspelling" in Vim

Is there a way to tell Vim not to highlight a word once? For example, in "the password is abc123", I don't want to add abc123 to the wordlist, but still wouldn't like the big red rectangle around it.
Clarification: I'm looking for a command that makes the spell checker ignore the current word (or last misspelling).
Without having the word stored somewhere, it's hard (not to say impossible) to ignore it always.
But, if you are looking to ignore the word really once, that is only for a moment, you can add it to the internal list with the zG command.
*zG*
zG Like "zg" but add the word to the internal word list
|internal-wordlist|.
*internal-wordlist*
The internal word list is used for all buffers where 'spell' is set. It is
not stored, it is lost when you exit Vim. It is also cleared when 'encoding'
is set.
When your cursor is positioned on a word that is highlighted as misspelled you can add it to your wordlist by pressing zg. Vim allows you to load more than one wordlist at a time, which makes it possible to have (for example) a global wordlist, and a project specific wordlist.
By default, when you run zg it will add the current word to the first spellfile it finds in your runtime path for the current encoding. In my case, that turns out to be ~/.vim/spell/en.utf-8.add when I'm working with UTF-8 encoding. Try running the following commands:
:setlocal spellfile+=~/.vim/spell/en.utf-8.add
:setlocal spellfile+=oneoff.utf-8.add
That will set you up so that zg (or 1zg) adds the current word to your default spellfile. But running 2zg would add the current word to a file called oneoff.utf-8.add, in the same directory as the file that you are working on. If the file doesn't exist, Vim will try to create it for you.
When you open the file again in the future, you will have to run the same two commands to make Vim check the oneoff.utf-8.add spellfile. Unfortunately, Vim does not allow you to set the spellfile option in a modeline, so if you want to run these commands automatically when the file opens, you would have to find some other way. This question includes a few ideas on how you might proceed.

How to implement own tag jump in VIM with CTRL-]?

If :h is used in VIM, it will automaticall follow |links| via CTRL+], opening new help topics and maintaining tag jumps list (CTRL+T will go back in jumps history). How to implement such behavior in my own file format? For example, i want CTRL+] on text inside {} to open a file named something.txt and CTRL+T to go back. How to implement this?
It's all done with tags. Essentially the vim files are simple text files, but they're supported by a file in the same directory named 'tags'. All this file contains is entries that look like:
'bg' options.txt /*'bg'*
'bh' options.txt /*'bh'*
'bin' options.txt /*'bin'*
'binary' options.txt /*'binary'*
'biosk' options.txt /*'biosk'*
'bioskey' options.txt /*'bioskey'*
Each line is a tag entry, split over three fields: the tag identifier, the file the tag lives in, and the ex command to find that tag: any ex command works; as can be seen in the example above though, the vim help files just use the search command: '/'.
You can either write a tags file manually, or use a program such as Exuberent ctags to create the file automatically. The tags file is generally read from the same directory the file you're editing lives in, but you can change this in Vim by adjusting the value of the 'tags' option.
More details in vim if you type ":help tags"

Resources