Split file by cursor position - vim

Let's say we have open a file xaa.txt and we are on a line 25.
Is there a command to split file xaa.txt into who files (xaaa.txt, xaab.txt) so
that lines 0..24 will be in file xaaa.txt and lines 25..50 will be in file xaab.txt?
The file names for spliting can be inserted as parameters.
I will do this operation often.

You can give a range to :w:
:1,24w xaaa.txt
:25,50w xaab.txt
Since you are on line 25, you can simplify the above to:
:1,-w xaaa.txt
:,50w xaab.txt
See :help :w and :help :range.
You can also build the new filenames from the current filename. Assuming you are in xaa.txt:
:1,24w %<a.txt
:25,49w %<b.txt
See :help extension-removal and the related :help filename-modifiers.

Related

Collect markdown headlines in vim?

I am trying to come up with a TOC (table of contents) of a text document:
lines starting with # (hashtag) VIM would "collect" into the buffer or maybe place them at the TOP OF FILE.
(Or - other idea - erase all lines in a duplicate file NOT starting with a #)
There must be solutions to this question...
I think you are looking for the :global command.
You can see all lines starting with # with :g/^#/p
and put them in a file using the :redir command :
:redir > toc.txt
:g/^#/p
:redir END
Note that toc.txt will contain the line numbers if you have set number. There is also this post on the subject.
Alternatively, you can delete all lines not starting with # with :v or :g! and save it to another file.
:v/\#/d
:w! toc.txt | undo
Look also for :copy (:t) and :move.
:global applies the command you provide to each matched lines in the order they appear in the file, so :g/^#/t0 will copy headers to the top of the file but in reverse. We could do :v/^#/m$ to move all non-header lines to the end, leaving the headers on top but stripped from the original text. Another way is to place some marker to mark the end of the table of content and copy header lines one line above this marker :
:g/^#/t?end-toc?-1

Vim: how to visual select up to characters with backspaces in

I have a *.qif file (text file) in which I would like to remove all lines from the second line (not including the header) to a line which contains the characters 'D1/7/2015'. In vim I have tried block selecting from the second line and searching up to a the characters but it doesn't work. What I have tried so far:
Move the cursor to second line then:
v/D1/7/2015
v/D1//7//2015
v/D1///7///2015
None of these seem to work.
You can escape slashes with backslashes:
v/D1\/7\/2015
or tell Vim to parse your pattern with "verymagic" syntax:
v/\vD1/7/2015
See :help \v.
Not exactly what I wanted but it works. I used /D1.7.2015 to get to the line then started visual selection up to the beginning of the file with vgg after which I moved one line down with the cursor then pressed d.
You can delete directly without using the visual selection from the second line to the line containing 'D1/7/2015' by executing the command below:
:2,/D1\/7\/2015/ d

Remove single line breaks but keep empty lines with Vim

Is it possible to remove single line breaks but to keep empty lines (double line breaks I guess?) in Vim? I'm using Vim's HardPencil plugin to do some word processing, and I like the hard line breaks because it makes it easier to bounce around the file. However, I need to share this information in LibreOffice Writer or Word, and hard line breaks won't work well if others edit the file. To clarify, this is what I have:
Line1.
Line2.
Line3.
Line4.
Line5.
And this is what I would like:
Line1. Line2. Line3.
Line4. Line5.
Essentially hard line breaks should be replaced with a space, and double line breaks should be preserved.
I've tried variations of :%s/\n but can't get the double line breaks to be preserved. I've found similar questions here and here, but these are not Vim specific.
You can replace line+line break with just line, and use negative look ahead \(\n\)\#! to make sure it's not followed by an empty line:
:%s/\(.\+\)\n\(\n\)\#!/\1 /
#Peter_Rincker's cleaner solution:
:%s/.\+\zs\n\ze./ /
Use gw (or gq) with a motion (like G).
gwG
gw is Vim's paragraph formatting operator which "reflows" text to the desired 'textwidth'. You may want to temporarily set 'textwidth' to 0 for unlimited text width (:set tw=0).
There some other ways as well do this as well:
Use :%!fmt- same idea as above but use fmt external tool and a filter.
:v/^$/,//-j - squeezes non-empty lines together. Fails if the end of the range does not have a blank line
:g/\v(.+\zs\n)+/,-//j - Also squeezes non-empty lines together, but avoids the range error of the previous method.
A substitution - See #Fabricator solution for an example
For more help see:
:h gw
:h operator
:h 'tw'
:h filter
:h :range!
:h :range
:h :v
:h :j
:h :g
:h magic
:h /\zs

How to add custom messages to Vim quicklist?

I have a file which contains code review comments by file and line numbers.
I'm writing a Vim plugin which uses Vim quicklist to display review comments when i open a file and navigate to the line number.
I've figured out that i can use :cex command to add entries to quicklist from this documentation
How do i add error message in a format like [file]:[line] [issue category][issue description] which allows me to jump to that location?
The help of :cexpr also provides the hint:
If {expr} is a String, then each new-line terminated
line in the String is processed using the global value
of 'errorformat' and the result is added to the
quickfix list.
:caddexpr printf('%s:%d:%s', expand('%'), line('.'), "entry")
Since the value of 'errorformat' is difficult and may not be completely under your control (ftplugins may change it), an alternative is to directly set / append items via the setqflist() Vimscript function:
:call setqflist([{'bufnr': bufnr(''), 'lnum': 42, 'text': 'entry'}], 'a')

Change wrap width in a text file using Vim

I want to format srt subtitle text files to avoid wrapping problems on my media player.
I need to set a line wrap width to a number of characters e.g. 43
I can do this with Editplus, its a built in function and works well. The reason I want to do it in Vim, firstly Editplus is only available on the PC and the secondly Vim is badass.
I have found the following solution on the net..
:set tw=43
gggqG
It does work, but not exactly how I want it.
E.g.
I have this text:
557
00:47:39,487 --> 00:47:42,453
I will have to complete some procedures,
and I asked you to check out what they are for me
after I format it, I get:
557 00:47:39,487 --> 00:47:42,453 I will
have to complete some procedures, and I
asked you to check out what they are for
me
It seems to ignore line breaks/CRs. As you can see the "I will" has been added to the first line.
How do I get it to not ignore line breaks?
EDIT: apoligies about the formatting, first time using stackoverflow!
You could use the whitespace option of formatoptions and make the lines you want to wrap end in whitespace.
:set tw=43
:set fo+=w
:g/^\a/s/$/ /
gggqG
The third line adds a space on the end of any line starting with a letter and fo+=w stops gq from joining lines that don't end in spaces.
See:
:help fo-table
:help 'formatoptions'
:help gq
:help :g
Edit in response to comments
:g/^\a/s/$/ /
This translates to:
:g/ " Search the file
^\a " For lines starting (^) with an alphabetic character (\a - equivalent to [A-Za-z])
/ " Then on each line that the regexp matches (i.e. each line starting with an alphabetic character)
s/ " Substitute...
$ " The end of line (zero-width match at the end of the line)
/ / " With a space (slashes are delimiters)
The global (:g) command will only operate on the current file, but the textwidth and formatoptions lines will last for the whole session. If you want those options to only be used on the current buffer, use :setlocal instead:
:setlocal tw=43
:setlocal fo+=w
:help :setlocal
If the only lines you want to wrap are the ones that start with text (ignore the ones that start with numbers) you can use the following.
:g/^[a-zA-Z]/normal gqq
This will run p00ya's command on each text line in the file.
With the following text (i.e. only 3 lines):
557
00:47:39,487 --> 00:47:42,453
I will have to complete some procedures, and I asked you to check out what they are for me
Use gqq (format current line) on the 3rd line after setting tw. Formatting by paragraph will not work since vim will treat all 3 lines as part of the same paragraph (paragraphs only end with a blank line).
While not exactly robust (or elegant), if you can assume that the subtitle lines do not begin with numbers, you can configure Vim to treat them as comments.
:set comments=:0,:1,:2,:3,:4,:5,:6,:7,:8,:9
gggqG
Lines starting with 0-9 will be treated as comments and won't be merged together with the text.
I can't see exactly what the issue is due to the formatting of your post, but you might want to checkout the 'formatoptions' setting in vim's help, specifically :he fo-table which contains a bunch of customization flags.
This link might be useful.

Resources