Word wrapping a txt file in vim not working as expected - vim

I am trying to edit a file on vim. You can download the txt file here.
I am following the instructions on this blog. I am also using what I read on StackOverflow.
First, I did this inside vim (command mode):
:set textwidth=80
Second, I used visual mode v to select all lines in the file. I started at the first line and the pressed G (goes to the last line). This made all the file selected.
Third, to reformat it, I did:
gq
Ok, the text is close to what I want. However, when I do this:
:echo max(map(range(1, line('$')), "col([v:val, '$'])")) - 1
The output is:
90
The command above shows me the length in characters of the lengthiest line. The output should be 80, not 90!
What I set as the limit of the text wrap was: 80
What mistake am I making? How can I wrap the text to 80 columns?
I started to use Vim this week. I am sorry if this question is too naive.

Your text width and reformatting is working fine, but the expression col is actually counting the "byte index" of the column position at the end of each line (not the character position). See :help col for all the info you need on how col works.
Instead, try using a character counting function like strchars:
echo max(map(range(1, line('$')), "strchars(getline(v:val))"))
On your example text I get an output of 83 because of the way the wrapping works on whitespace which count as characters. To take care of that, you could trim trailing whitespace with something like :%s/\s*$//, and now my example expression above using strchars returns 80 as expected.

:help col() gives you the byte index of the column. This would work as expected if you only had single-byte characters like c or a but your text contains a lot of characters like ç (U+00e7) or á (U+00e3) which are encoded with more than one byte so the count will be off for many lines.
What you actually want is to count screen columns, with :help virtcol().

Related

How do I break a really long line into smaller lines of 64 characters each in vim?

I have a very long set of characters around 1000 characters long without any spaces in them. Can I break them neatly into rows of 64 characters each in vim. For example,
I want to convert a string like this:
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDOgwPQvZf9l3WYA/+eMcjz+v/1aWrebfpVLCOMDPN/mvWpG5cufxirk9nmX1yqzeYoIyrXsJ2MfCLdidf3nZ6wmBkKXq8dk51fG7+NzuG15UWtsZSp4z2fbVMWhulcUtj39zXCPCqFqk/St+Gc2SKZOOLi6TuvlsJAPGVS+shJJXeCZPBRiqEQhXZE7zsVrKFCM2tFZp1RLE9TWB+LNYOYg6/KES+iVwjqY4CcVqKMA6frUC/7N/Q9U7pvJbZiMRh4ScdnyEzJMvcIJcItt/0piZCZyOaVIv15RVOG4b9E0BMgEEtOvVgD+tLqKus/fdWz/hdtyVjDIlc5mzQnl98TAgMBAAECggEBAJnWpZ/5rOD/1F0jFWgOZEnEgKqcFj2Opf6O/AgXmclEcZ7Ba/T6PzGJ2bgw8AJZkgvybrbw3dzKmNp6FkViyNV66KR99mvNDF3OePs105TCMA79i+am3sAGG/BbHjpliTXnlceVNIQQZJhv3QUQCCMmanZpEspyP1DE7SJMqak6hh+irTx9n1Z+Eh8ma3hZ0vTpy5w96eWOk2NRGOMrUikEMApsBxI1W4HkrG3WI0MlWnLLv/DyGbIwiqp3Q2l39vKO/S5K3A8NVOuHbOvqHrP96g3a4srozu34tzXIcghxwECNx5mpouw4/lo53Ybo8JiNcU8s8fEmY6ufLaL0BlkCgYEA7y3Y6yIWPN04sK9jPZ/8hc6XzpelmFkc6d7kRDxTv3dWsWZAgos8a2zsKBmVFXJ7Aq2aNx+nmGPnYxr24Mu65NDfrd+rki4HxTqO0tkL9KI66y4F+yd796tkdqkLSyu5u9eci6hNaGeaJaX3es3Mq0J2i9hQ793XWXyv6mRh3dUCgYEA3QkHbhwd6KuE0AtI6P1e9dBn7DQip8VuJjY78qbFAMVEwJsn/aBL5CbzScCiIs8/wsx30LgbLPmPbVd0kfjrb9/eLKdej6EyZkLgrIUKBxSpg1f86TTCz0F3RUEiGBPtvFpJHfMVFjXGktUAyBvJyDTZjSSq79h7IPb3j+lNdUcCgYBGGLK1HrVTuyXtKkm0etngQU7eXjVK8/r0U72kfeWxfIEs1qHbYIEhnreLfQvjUDza6RQEScOtdsIOmo12Dl9Exi5339CBs/nVBLds9e16Eb2gxUk9dTHwwQtdd2d27WautZ8MkxO0oIBdvklMdVohawYhMBFwaxy8/jz0Pd0szQKBgEZ0jFPCzp3NnmYaUsFBkjVUmuulqq5DtlqjyvQLyJv4RXQHgPXNVKOC7uXBa20hFrfnKQH0zWTGn7tAtz2YVKOyfkVJjFDIFyKVirwzJAEhyu686zcCxF4ABh6jJlT6dTsmpEvRohUUSxmen8MpaGZSwk3FNF+DZ6wYTM0olrIdAoGBAKMc/LEIxgqwpFIzxIsFj4lSaGwIWFimMSq/9gd9R60/gncaBearSXrNwVBHPqfZBFnGeLTiddD7F/x/LbcPip+Hj0/PFphAxWfPfgLrTl2cGf4975mJbny11WjD+WucpB3YsXoOjo+z4rX0g4JmRuM0XDFy/ef11BMMQ2wjBZ54
to:
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDOgwPQvZf9l3WY
A/+eMcjz+v/1aWrebfpVLCOMDPN/mvWpG5cufxirk9nmX1yqzeYoIyrXsJ2MfCL
didf3nZ6wmBkKXq8dk51fG7+NzuG15UWtsZSp4z2fbVMWhulcUtj39zXCPCqFqk
/St+Gc2SKZOOLi6TuvlsJAPGVS+shJJXeCZPBRiqEQhXZE7zsVrKFCM2tFZp1RL
E9TWB+LNYOYg6/KES+iVwjqY4CcVqKMA6frUC/7N/Q9U7pvJbZiMRh4ScdnyEzJ
MvcIJcItt/0piZCZyOaVIv15RVOG4b9E0BMgEEtOvVgD+tLqKus/fdWz/hdtyVj
DIlc5mzQnl98TAgMBAAECggEBAJnWpZ/5rOD/1F0jFWgOZEnEgKqcFj2Opf6O/A
gXmclEcZ7Ba/T6PzGJ2bgw8AJZkgvybrbw3dzKmNp6FkViyNV66KR99mvNDF3Oe
Ps105TCMA79i+am3sAGG/BbHjpliTXnlceVNIQQZJhv3QUQCCMmanZpEspyP1DE
7SJMqak6hh+irTx9n1Z+Eh8ma3hZ0vTpy5w96eWOk2NRGOMrUikEMApsBxI1W4H
krG3WI0MlWnLLv/DyGbIwiqp3Q2l39vKO/S5K3A8NVOuHbOvqHrP96g3a4srozu
34tzXIcghxwECNx5mpouw4/lo53Ybo8JiNcU8s8fEmY6ufLaL0BlkCgYEA7y3Y6
yIWPN04sK9jPZ/8hc6XzpelmFkc6d7kRDxTv3dWsWZAgos8a2zsKBmVFXJ7Aq2a
Nx+nmGPnYxr24Mu65NDfrd+rki4HxTqO0tkL9KI66y4F+yd796tkdqkLSyu5u9e
ci6hNaGeaJaX3es3Mq0J2i9hQ793XWXyv6mRh3dUCgYEA3QkHbhwd6KuE0AtI6P
1e9dBn7DQip8VuJjY78qbFAMVEwJsn/aBL5CbzScCiIs8/wsx30LgbLPmPbVd0k
fjrb9/eLKdej6EyZkLgrIUKBxSpg1f86TTCz0F3RUEiGBPtvFpJHfMVFjXGktUA
yBvJyDTZjSSq79h7IPb3j+lNdUcCgYBGGLK1HrVTuyXtKkm0etngQU7eXjVK8/r
0U72kfeWxfIEs1qHbYIEhnreLfQvjUDza6RQEScOtdsIOmo12Dl9Exi5339CBs/
nVBLds9e16Eb2gxUk9dTHwwQtdd2d27WautZ8MkxO0oIBdvklMdVohawYhMBFwa
xy8/jz0Pd0szQKBgEZ0jFPCzp3NnmYaUsFBkjVUmuulqq5DtlqjyvQLyJv4RXQH
gPXNVKOC7uXBa20hFrfnKQH0zWTGn7tAtz2YVKOyfkVJjFDIFyKVirwzJAEhyu6
86zcCxF4ABh6jJlT6dTsmpEvRohUUSxmen8MpaGZSwk3FNF+DZ6wYTM0olrIdAo
GBAKMc/LEIxgqwpFIzxIsFj4lSaGwIWFimMSq/9gd9R60/gncaBearSXrNwVBHP
qfZBFnGeLTiddD7F/x/LbcPip+Hj0/PFphAxWfPfgLrTl2cGf4975mJbny11WjD
+WucpB3YsXoOjo+z4rX0g4JmRuM0XDFy/ef11BMMQ2wjBZ54
Thanks for reading.
If calling external commands is ok you could use the fold command:
fold -w64 file
To apply the command within vim, you could do a visual selection of your string and then:
:'<,'>!fold -w64 %
Or to apply the command to the current line:
:.!fold -w64 %
Without external command this could work:
:.s#.\{64\}#&\r#g
From the man page:
An ampersand (&) appearing in the replacement is replaced by the string matching the RE
:set textwidth=64
gqgq
:set textwidth=0
It sets the limit to the maximum line length, reindents current line, and returns the limit back to the default value (I assume you use the default value)
Qa64l<enter>q16#a:w
This will record a macro to hit enter after moving to the right 64 times under the alias a, and will run that macro 16 times and save the file. Should do what you’re asking.

Write output from command line into file in vim

I would like to insert at the end of each line the number of alphabetic characters on that line. To do this on one line is easy. I search using :s/\a//gn and get the occurrence of alphabetic characters in the command line and then A and space and enter the number.
My problem arises when I have so many lines that it becomes extremely tedious to do this. I am trying to create a macro but am having difficulty getting command line output into it. Is there a way to do this without resorting to *nix commands? I have access to a *nix box but not all the time.
So if my file had the following content:
abc2d4s
jd4a5ag
jdf7fjf
abdd5ff
I would like the output to look like this:
abc2d4s 5
jd4a5ag 5
jdf7fjf 6
abdd5ff 6
I was thinking if there was a way to get the replace output piped into the register somehow but cannot figure out how to do it, but maybe there is a better way.
You can capture the output of the :s///gn command with :redir, but in this case, I would rather implement the counting via substitute() and :help sub-replace-expression:
:%s/.*/\=submatch(0) . ' ' . len(substitute(submatch(0), '\A', '', 'g'))/
This matches the entire line (.*), then removes all non-alphabetic characters (\A), and appends the length of the result. Note: Works only for ASCII characters (but \a covers only those, anyway)!
this cmd should give you that output:
%s/.*/\=submatch(0).' '.(len(submatch(0))-len(substitute(submatch(0),'\a','','g')))
One way to do that would be to use a simple macro:
:%norm A <C-v><C-r>=col('.')-2<C-v><CR>
which should look like:
:%norm A ^R=col('.')-2^M
where we enter insert mode at the end of each line and insert a space followed by the column number of the last character.
A variant:
:%norm A^R=" ".len(getline('.'))^M

How to unwrap text in Vim?

I usually have the tw=80 option set when I edit files, especially LaTeX sources. However, say, I want to compose an email in Vim with the tw=80 option, and then copy and paste it to a web browser. Before I copy and paste, I want to unwrap the text so that there isn't a line break every 80 characters or so. I have tried tw=0 and then gq, but that just wraps the text to the default width of 80 characters. My question is: How do I unwrap text, so that each paragraph of my email appears as a single line? Is there an easy command for that?
Go to the beginning of you paragraph and enter:
v
i
p
J
(The J is a capital letter in case that's not clear)
For whole document combine it with norm:
:%norm vipJ
This command will only unwrap paragraphs. I guess this is the behaviour you want.
Since joining paragraph lines using Normal mode commands is already
covered by another answer, let us consider solving the same issue by
means of line-oriented Ex commands.
Suppose that the cursor is located at the first line of a paragraph.
Then, to unwrap it, one can simply join the following lines up until
the last line of that paragraph. A convenient way of doing that is to
run the :join command designed exactly for the purpose. To define
the line range for the command to operate on, besides the obvious
starting line which is the current one, it is necessary to specify
the ending line. It can be found using the pattern matching the very
end of a paragraph, that is, two newline characters in a row or,
equivalently, a newline character followed by an empty line. Thus,
translating the said definition to Ex-command syntax, we obtain:
:,-/\n$/j
For all paragraphs to be unwrapped, run this command on the first line
of every paragraph. A useful tool to jump through them, repeating
a given sequence of actions, is the :global command (or :g for
short). As :global scans lines from top to bottom, the first line
of the next paragraph is just the first non-empty line among those
remaining unprocessed. This observation gives us the command
:g/./,-/\n$/j
which is more efficient than its straightforward Normal-mode
counterparts.
The problem with :%norm vipJ is that if you have consecutive lines shorter than 80 characters it will also join them, even if they're separated by a blank line. For instance the following example:
# Title 1
## Title 2
Will become:
# Title 1 ## Title 2
With ib's answer, the problem is with lists:
- item1
- item2
Becomes:
- item1 - item2
Thanks to this forum post I discovered another method of achieving this which I wrapped in a function that works much better for me since it doesn't do any of that:
function! SoftWrap()
let s:old_fo = &formatoptions
let s:old_tw = &textwidth
set fo=
set tw=999999 " works for paragraphs up to 12k lines
normal gggqG
let &fo = s:old_fo
let &tw = s:old_tw
endfunction
Edit: Updated the method because I realized it wasn't working on a Linux setup. Remove the lines containing fo if this newer version doesn't work with MacVim (I have no way to test).

vim command to restructure/force text to 80 columns

I know there are ways to automatically set the width of text in vim using set textwidth (like Vim 80 column layout concerns). What I am looking for is something similar to = (the indent line command) but to wrap to 80. The use case is sometimes you edit text with textwidth and after joining lines or deleting/adding text it comes out poorly wrapped.
Ideally, this command would completely reorganize the lines I select and chop off long lines while adding to short ones. An example:
long line is long!
short
After running the command (assuming the wrap was 13 cols):
long line is
long! short
If this isn't possible with a true vim command, perhaps there is a command-line program which does this that I can pipe the input to?
After searching I found this reference which has some more options: http://www.cs.swarthmore.edu/help/vim/reformatting.html
Set textwidth to 80 (:set textwidth=80), move to the start of the file (can be done with Ctrl-Home or gg), and type gqG.
gqG formats the text starting from the current position and to the end of the file. It will automatically join consecutive lines when possible. You can place a blank line between two lines if you don't want those two to be joined together.
Michael's solution is the key, but I most often find I want to reformat the rest of the
current paragraph; for this behavior, use gq}.
You can use gq with any movement operators. For example, if you only want to reformat to the end of the current line (i.e. to wrap the line that your cursor is on) you can use gq$
You can also reformat by selecting text in visual mode (using `v and moving) and then typing gq.
There are other options for forcing lines to wrap too.
If you want vim to wrap your lines while you're inserting text in them instead of having to wait till the end to restructure the text, you will find these options useful:
:set textwidth=80
:set wrapmargin=2
(Don't get side-tracked by wrap and linebreak, which only reformat the text displayed on screen, and don't change the text in the buffer)
Thanks to a comment from DonaldSmith I found this, as the textwidth option didn't reformat my long line of text (I was converting playing with hex-to-byte conversions):
:%!fold -w 60
That reformated the whole file (which was one line for me) into lines of length 60.
If you're looking for a non-Vim way, there's always the UNIX commands fmt and par.
Notes:
I can't comment on Unicode, it may or may not behave differently.
#nelstrom has already mentioned using par in his webcast.
Here's how we would use both for your example.
$ echo -e 'long line is long!\nshort' > 3033423.txt
$ cat 3033423.txt
long line is long!
short
$ fmt -w 13 3033423.txt
long line is
long! short
$ par 13gr 3033423.txt
long line is
long! short
To use from inside Vim:
:%! fmt -w 13
:%! par 13gr
You can also set :formatprg to par or fmt and override gq. For more info, call :help formatprg inside Vim.
Almost always I use gq in visual mode. I tell my students it stands for "Gentlemens' Quarterly," a magazine for fastidious people.

How to add line numbers to range of lines in Vim?

How can I add line numbers to a range of lines in a file opened in Vim? Not as in :set nu—this just displays line numbers—but actually have them be prepended to each line in the file?
With
:%s/^/\=line('.')/
EDIT: to sum up the comments.
This command can be tweaked as much as you want.
Let's say you want to add numbers in front of lines from a visual selection (V + move), and you want the numbering to start at 42.
:'<,'>s/^/\=(line('.')-line("'<")+42)/
If you want to add a string between the number and the old text from the line, just concatenate (with . in VimL) it to the number-expression:
:'<,'>s/^/\=(line('.')-line("'<")+42).' --> '/
If you need this to sort as text, you may want to zero pad the results, which can be done using printf for 0001, 0002 ... instead of 1, 2... eg:
:%s/^/\=printf('%04d', line('.'))/
Anyway, if you want more information, just open vim help: :h :s and follow the links (|subreplace-special|, ..., |submatch()|)
cat -n adds line numbers to its input. You can pipe the current file to cat -n and replace the current buffer with what it prints to stdout. Fortunately this convoluted solution is less than 10 characters in vim:
:%!cat -n
Or, if you want just a subselection, visually select the area, and type this:
:!cat -n
That will automatically put the visual selection markers in, and will look like this after you've typed it:
:'<,'>!cat -n
In order to erase the line numbers, I recommend using control-v, which will allow you to visually select a rectangle, you can then delete that rectangle with x.
On a GNU system: with the external nl binary:
:%!nl
With Unix-like environment, you can use cat or awk to generate a line number easily, because vim has a friendly interface with shell, so everything work in vim as well as it does in shell.
From Vim Tip28:
:%!cat -n
or
:%!awk '{print NR,$0}'
But, if you use vim in MS-DOS, of win9x, win2000, you loss these toolkit.
here is a very simple way to archive this only by vim:
fu! LineIt()
exe ":s/^/".line(".")."/"
endf
Or, a sequence composed with alphabet is as easy as above:
exe "s/^/".nr2char(line("."))."/"
You can also use a subst:
:g/^/exe ":s/^/".line(".")."^I/"
You can also only want to print the lines without adding them to the file:
"Sometimes it could be useful especially be editing large source files to print the line numbers out on paper.
To do so you can use the option :set printoptions=number:y to activate and :set printoptions=number:n to deactivate this feature.
If the line number should be printed always, place the line set printoptions=number:y in the vimrc."
First, you can remove the existing line numbers if you need to:
:%s/^[0-9]*//
Then, you can add line numbers. NR refers to the current line number starting at one, so you can do some math on it to get the numbering you want. The following command gives you four digit line numbers:
:%!awk '{print 1000+NR*10,$0}'
The "VisIncr" plugin is good for inserting columns of incrementing numbers in general (or letters, dates, roman numerals etc.). You can control the number format, padding, and so on. So insert a "1" in front of every line (via :s or :g or visual-block insert), highlight that column in visual-block mode, and run one of the commands from the plugin.
If someone wants to put a tab (or some spaces) after inserting the line numbers using the this excellent answer, here's a way. After going into the escape mode, do:
:%s/^/\=line('.').' '/
^ means beginning of a line and %s is the directive for substitution. So, we say that put a line number at the beginning of each line and add 4 spaces to it and then put whatever was the contents of the line before the substitution, and do this for all lines in the file.
This will automatically substitute it. Alternatively, if you want the command to ask for confirmation from you, then do:
:%s/^/\=line('.').' '/igc
P.S: power of vim :)
The best reply is done in a duplicate question.
In summary:
with CTRL-V then G I 0 You can insert a column of zero.
Then select the whole column and increment:
CTRL-V g CTRL-A
See also: https://vim.fandom.com/wiki/Making_a_list_of_numbers#Incrementing_selected_numbers

Resources