Vim gF should open file and jump to line - vim

I tried out gF and it seems to not behave like mentioned in :help gF
If cursor is positioned on an entry x.c and I type gf the file is opened.
If cursor is positioned on an entry x.c:3 and I type gF I get E447: Can't find file "x.c:3" in path. Whereby :3 should tell vim to jump to line 3.
What do I miss?

Enter :set isfname
It'll show an OS dependent list of all characters considered being possibly part of a file name. On my system (Windows), the column : appears in the list.
isfname=#,48-57,/,\,.,-,_,+,,,#,$,%,{,},[,],:,#-#,!,~,=
Hence it won't be considered by gF as a separator between file name and line number. However if I add a space between them, the behaviour goes as documented.
Given how no sane person uses : in a file name, if you want to use gF on some compiler's output that says file.c:120, you can add this to your vimrc :
set isfname-=:
(mind the - before the =)
If ever one day you need to open a file that has a : in its name, you can always enter :set isfname+=: to restore the column as a valid file name character for the duration of that session.

Related

How to paste contents of a register specifying a line number?

Assume a text file with 5 lines, each having a line break. This text file is opened in gvim. While in command mode and cursor in line number 1, the content of current line is yanked into default register.
How to paste/put yanked to different line number without moving the cursor? For example, cursor is in line number 1. Yanked content should be put in line number 4. How to do this in gvim without moving the cursor to line number 4?
The cursor position is an important part of command addressing; for interactive editing, it does not make sense to have commands that work "at a distance". (Inside Vimscript you can use low-level functions like setline() to modify arbitrary places, but that should not be part of normal use, and here I disagree with #SergioAraujo's answer, which presents this command as suitable for interactive use.)
Instead, Vim makes it easy to temporarily go to a location and then return back to where you came from. The :help jumplist and especially CTRL-O are for that. Your example paste you be done via 4Gp<C-O> or 4Gp``; to use Ex commands, you have to explicitly set the jump point: m':4put<CR>``. The advantage of working with the jumplist is that the paste target now also became part of it, so you can easily go forward (with <C-I>) to it, too.
Here an example:
:call setline(4, getline(4) . " " . #")
We are setting line 4 to line 4 itself plus space " "
plus default register #" .
Just In case you want just put the content
of the line 1 on the line 4 type:
:call setline(4, getline(1))
Use the :t command (a synonym for :copy). Examples:
:1t 4
:.t 4

vim - replace mode to replace new lines too

In VIM's replace mode, as you type, you don't add any new content, you just replace what is already there. Only problem is that you can add new content when you press enter. I'd like to know if there is a way so that pressing enter (or ^M) will be interpreted as down arrow when you're in replace mode?
If you must know, I'm working in a file that has segments that are given a fixed number of lines. I can't add new lines because it will offset subsequent segments.
Thanks in advance!
As far as I understand your requirements this can be achieved in the virtual replace mode. You can enter it via gR.
Typing a <NL> still doesn't cause characters later in the file to appear to
move. The rest of the current line will be replaced by the <NL> (that is,
they are deleted), and replacing continues on the next line. A new line is
NOT inserted unless you go past the end of the file.
Please note that vim has to be compiled with +vreplace.

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

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.

How to make vim indicate the file has changed since last save?

I used to work with netbeans and it always put an asterisk and changed the tab color when the file had changed since last save. Is there any way to make vim do something similar, that is, remind me that I haven't saved the file?
I know that there is a way to have it save automatically once in a while, but I don't want to do that.
You can use the m flag in the 'statusline' option to add a [+] if file is modified. Note that in order to see the statusline, you'll need to set 'laststatus' to be greater than 0 (1-Only shows status line if there are two or more windows, 2-Always).
If you're using a GUI-version, such as MacVim, you may prefer to set 'titlestring', which uses the same syntax but will alter the name of the window in your window-manager.
Example:
:set laststatus=2
:set statusline=[%n]\ %<%f%h%m
This will display:
[: literal
%n: buffer number
]: literal
\<Space>: a space
%<: Truncate the field at the beginning if too long
%f: Path to the file in the buffer, as typed or relative to current
directory.
%h: Help buffer flag, text is "[help]".
%m: Modified flag, text is "[+]"; "[-]" if 'modifiable' is off.
For more information see:
:help status-line
Call :ls and you will see a + before unsaved buffers
If the terminal displays its title somewhere, it's possible to use
:set title
to display whether the file is modified: a + is displayed after the file name if it's modified.
However, a file can have + at the end of its file name. For most files this should work fine.
Source: https://stackoverflow.com/a/13244715/5267751
Pressing Ctrl+g (or equivalently :f) in normal mode will show the file status, which indicates whether the file is modified.
The status looks like this
"file_name" 100 lines --20%--
if the file is not modified, or
"file_name" [Modified] 100 lines --20%--
if the file is modified.
For more info see :help ^g.

Vim: insert text from a file at current cursor position

To insert text from a file in the current Vim buffer I use :r filename to insert the text below the cursor or :0r filename to insert in the first line.
How do you insert the contents of a file where [Cursor] is located?
Actual line with some coding [Cursor] // TODO for later version
Line below actual line ...
This inserts the contents of the file whose path is at the cursor position:
:r <cfile>
Insert a line break, read the file, and then take out the line break...
I propose Ctrl-R Ctrl-O = join(readfile('filename','b'), "\n")
Other solution:
Possibly open the other file in another window, use :%yh (h is a register name) and in your original file, in normal mode use "hp or "hP or in insert mode, Ctrl-R Ctrl-O h
To expand on the accepted answer with actual code, since I tried the suggestion and it worked nicely;
Here is an example of it working to insert a little php snippet:
`nnoremap <leader>php a<CR><ESC>:.-1read $SNIPPETS/php<CR>I<BS><ESC>j0i<BS><ESC>l`
In general the syntax is
`nnoremap [KEY SEQUENCE] a<CR><ESC>:.-1read [FILE PATH]<CR>I<BS><ESC>j0i<BS><ESC>l`
Just to break it down:
nnoremap : I'm about to define a new key mapping for normal mode
<leader>php : I would like to trigger the command sequence when this key combination is pressed. In my case <leader> is , so I type ,php to trigger the command.
Now for the command, bit by bit:
a<CR><ESC> : go into insert mode (after the cursor), insert a line break, go back into normal mode.
:.-1read <file><CR> : this enters the desired file on the line above the current line.
I<BS><ESC> : jump to the start of the line, delete line break, return to normal mode.
j0i<BS><ESC>l : Go down one line (to the remainder of the line that you were initially on), jump to the start, enter insert mode, delete the line break, return to normal mode.
l : position the cursor to the right of the pasted file (this just made the command work more like how you expect it to).
note
You have a choice of whether to paste before or after the cursor. I have chosen in this example to paste after the cursor because that is how the p command usually works to paste yanked text. Alternately, to paste before the cursor you should change the a at the start of the command to an i. You could use one of these exclusively, or you could bind them both to different but related key sequences. For example:
`nnoremap <leader>php i<CR><ESC>:.-1read $SNIPPETS/php<CR>I<BS><ESC>j0i<BS><ESC>l`
Could paste text before the cursor,
and :
`nnoremap <leader><leader>php a<CR><ESC>:.-1read $SNIPPETS/php<CR>I<BS><ESC>j0i<BS><ESC>l`
could paste text after the cursor. Or vice versa. I have made 'before the cursor' easier to trigger because I use it more often when pasting in-line.
other note
This solution is mainly useful if you're reading from a file that you expect to use often enough that it's worthwhile setting up a key mapping for it (ie reading a snippet from a file). This doesn't really help if you just want to read in a random files whenever since you won't have the key mapping ready.
Since it is very formulaic, I'm sure it would be possible to define a function that would take the file name as an argument and do the same thing though. I've never written a function in vimscript though so if someone who knows more feels like editing this answer to contain that solution - I urge them to do so!
" put this in your ~/.vimrc
" in insert mode press ,n
"
imap ,n <c-r>=expand("%:p")<cr>
Read more in wikia.

Resources