Vim hides lines that are too long to be displayed completely - vim

Editing a document where I didn't bother to make line breaks, I noticed that Vim (MacVim 8.0 to be precise), instead of just showing that part of the line that fits, completely hides lines of text that are too long to fit on the current screen. The space that would be occupied by the part of the line that does fit is simply left blank, as if the characters had become invisible.
Is there a way to change that behaviour?

If I understand your problem correctly, setting :set display=lastline will help.
Change the way text is displayed. This is comma separated list of
flags:
lastline When included, as much as possible of the last line
in a window will be displayed. "###" is put in the
last columns of the last screen line to indicate the
rest of the line is not displayed.
truncate Like "lastline", but "###" is displayed in the first
column of the last screen line. Overrules "lastline".
uhex Show unprintable characters hexadecimal as <xx>
instead of using ^C and ~C.
When neither "lastline" nor "truncate" is included, a last line that
doesn't fit is replaced with "#" lines.
You can also try :set nowrap.

Related

How to fix problem with tabstop configuration in ~/. vimrc

I set tab configuration in ~/.vimrc as below:
set ts=4 sts=4 sw=4
I notice that if the word is 4 characters long or above, the cursor shift into right 4 spaces as in configuration for tabstop.
But if the word is less than 4 characters long, it didn't shift into 4 spaces.
Example:
'name' + <Tab>: tab produced correct number of spaces (i.e 4 spaces)
'age' + <Tab>: tab produced wrong number of spaces (i.e 1 space only)
Why is it ?
Does the word length effect tab?
What can I do if I want to shift the cursor to 4 spaces as configured regardless of the word length?
Thanks a lot
You’re probably inserting regular tabs, which display variable-width according to what’s before and after. I find having set list on is really handy for this (though you probably won’t like the default listchars settings).
If you really want spaces (which I find better anyway, set expandtab.
Also, most long-time users recommend leaving tabstop at 8, since you can’t control how wide every one’s tabs are.
The way that the tabstop, shiftwidth, and softtabstop options work is that they control indentation to certain points that are commonly referred to as "tab stops". In other words, they're designed to always indent to a column that's a multiple of the setting.
So if your tab stops are at multiples of 4, then hitting the Tab key will cause the cursor to indent to a column that is the next multiple of 4. This is the behavior of inserting a literal tab (U+0009, CHARACTER TABULATION) into a document and then rendering it on a normal terminal (except that the width is usually 8 there). This results in text that is aligned at fixed columns, which is the desired style for most programming languages and text markup formats.
As you've noted, this does result in different amounts of indent if the words are different lengths. Typically in code, we would just cause the second column to be at the next tab stop and not care that the indents are of different lengths. That is, in your example, we'd hit Tab once on the first line and twice on the second, and start the next column at column 8.
I'm not aware of any way to force Vim to insert a specific number of spaces other than the standard editing commands. Normally users who are in this situation just hit Space four times if they really want four spaces and not an indentation to the next tab stop. You can of course create a mapping if you need to do that a lot.

How to append each line from 11-20 to each line from 1-10 in VIM

I have a file in which first 10 lines are the columns of a table and the rest 10 lines are the values of each column.
How can I use norm in VIM to append the values after each column names like this:
column1
...
column10
value1
...value10
-->
column1: value1
...
column10: value10
It is a little similar with this(Vim - Copy Nth word of each line, from line 10-100, to end of line), but I don't know how to go to line 1:10 and append the copied lines.
Any idea will be appreciated!
Fairly naive and crude way to do this, but:
:1,10norm! 10j0d$10kA: ^[p
Explanation:
1,10norm!: for lines 1 to 10, do the following (the ! means any custom mapping you have will be ignored, thanks to D. Ben Knoble for reminding of this):
10j: move down 10 lines
0d$: delete the whole line (not including newline)
10k: move back up 10 lines
A:: append (at the end of the line) ': ' (note the trailing space)
^[: input escape character, going back to normal mode. This (^[) is a single character and is inputted by typing Ctrl-v then escape, not by typing ^[.
p: paste the line deleted in step 3
Another (copy-pastable) way, (ab)using the substitute command:
:1,10s/\v(.*)\ze(.*\n){10}(.*)/\1: \3/ | 11,20d
which does:
1,10s/: for lines 1 to 10, execute the following substitution:
\v: use very-magic regex mode (see :help \v)
(.*): capture the entire current line (eg column1)
\ze: signal the end of the match. This way everything read (and captured) afterwards will not be affected (but can still be read)
(.*\n){10}: skip 10 (including current) lines, ie skip selector to 10 lines below
(.*): capture the line (eg value1)
/: end the 'select' part of the substitute command
\1: \3: replace with captured groups (eg column1: value1)
|: command separator
11,20d: delete lines 11 to 20
Use blockwise-visual mode to perform the operations.
You can enter visual block mode with Ctrl-V and it allows you to select and operate on columns. It also allows you to perform the same action on a block, which you can use to add the : to the lines with the column names.
I'll use normal Vim syntax for keystrokes in my examples, <C-v> means Ctrl-V.
Start by deleting the values into the default register, using a visual block:
11G<C-v>9j$d
Then Add the : to the column lines, also using a visual block:
1G<C-v>9j$A: <Esc>
Then add some more spaces to the first line, to ensure there's room for all the column names to fit:
A <Esc>
Finally, put the visual block at the end of the first line:
$p
It will actually put it on all lines all the way to the end.
This is slightly different from what you specified, since the values are all aligned on the same column. If you want different spacing, you can perhaps use a :s operation to fix spacing.
10:s/: */: /<cr>
Depending on where you pasted (if some column names had more trailing spaces than the first one), you might have some trailing spaces after the pasted values to fix as well, but that should be easy to do using a similar procedure.
Visual block operations are really powerful, it's a great feature to learn and keep in your "toolbox" in Vim. They're really handy with this kind of problem where thinking in "columns" makes the most sense.

Limiting text width does not work as expected if not inserting at the end of a line

I know we can use :set tw=80 to limit the text width. However, if we insert text before the end, this function doesn't work at all.
For example, let's say we type "Would you like to have responses to your questions sent to you via email?"
If we continue to input after "?", tw works fine. But if we insert before say "have", it doesn't break off the line even if it exceeds the specified text width.
Is there any way to make this work in the latter case?
You may try
:set fo+=a
which reformats your paragraph as you type.
See :h fo-table.
This might be configurable using formatoptions or formatexpr, but I'm not sure how.
Another solution is to manually format using gq on a visual line selection i.e. add a breakline if the text width is >= tw.
Type in whatever text you like inside another block of text, thus making it 80 chars or more in width
Select the text you think is misformatted using V (Shiftv)
gq
From :h gq:
Format the lines that {motion} moves over.
Formatting is done with one of three methods:
1. If 'formatexpr' is not empty the expression is
evaluated. This can differ for each buffer.
2. If 'formatprg' is not empty an external program
is used.
3. Otherwise formatting is done internally.
In the third case the 'textwidth' option controls the
length of each formatted line (see below).
If the 'textwidth' option is 0, the formatted line
length is the screen width (with a maximum width of
79).
The 'formatoptions' option controls the type of
formatting fo-table.
[..]
For more information on how Vim's textwidth works, take a look at
How to use Vim’s textwidth like a pro

Placing characters at a specific column in vi

Is there a way to place a character at a specific line in vim, even if the line is short?
For example, I'm contributing to a project which has a comment block style which is 79 columns wide, with a comment character at either end e.g.
!--------------!
! Comment !
! More Comment !
!--------------!
but it's really annoying to space over to it, even with guessing large numbers (35i< SPACE>< ESC>)
Is there a simple command which will do this for me, or a macro or something I could write?
set ve=all
then you could move (h,j,k,l) to anywhere you want. no matter how short your line is.
there are 4 options block, all, insert, onemore for details:
check :h virtualedit
in this way, after you typed short comment, then type <ESC>080l to go to the right place to the tailing !
you can map it too, if it is often used
then it works like this:
Put this in your .vimrc file and restart vim:
inoremap <F1> <C-r>=repeat(' ', 79-virtcol('.'))<CR>!<CR>
With this just press F1 (or whatever key you map) in insert mode after entering comment text to automatically pad with spaces and insert a ! in column 79.
Another simple way is to keep an empty comment box of the correct size somewhere, yank/paste it where needed and just Replace the spaces in it with your comment each time.
If you want to reformat a box that is too short, one way is to start from the comment in your example, make a Visual Block (Ctrl+v) selecting the single column just to the left of its right-hand edge, yank it (y), then repeatedly paste it (p). This will successively move the entire right-hand side of the comment one step, extending the box rightward. Repeat until it has the desired length.
If you already entered the comment text, you can use a macro to add the right-hand ! mark at the correct place. For example, record a macro (qa) that appends more characters than are needed for any line (e.g. 80ASpaceEsc), then use the goto column (|) to go to the correct place (79|) and replace the excess characters from there (C!Esc), then move down one line (j), and stop recording (q). Repeating this macro (#a) then "fixes" each line in turn and moves to the next. In total: qa80A<space><esc>79|C!<esc>jq and then #a whenever needed. Sounds complex but is convenient once you have it.
There are certainly good answers here already, particularly the virtualedit answer. However, I don't see the method which seems most intuitive to me. I would create an empty line for the last row of the comment which is just surrounded by the exclamation points. Then I would yank and paste a new copy of the empty line, go to the old empty line and go to the point at which I want to edit and use overstrike mode (R) to add my text without affecting the placement of the ending exclamation point.
Sometimes the simplest methods, while slightly more clunky, are the easiest to use and remember.
I usually just copy and paste an existing line in the comment block (or copy one from another file) and then modify it. If the text you're replacing is about the same size as what you want to write (e.g., if you're changing the author's name), you probably only need to add or delete a few spaces to make everything line up. It's a lot less painful than spacing out to the desired width.
If you ever have a block that gets too long this way, a neat trick is to place the cursor on the 79th column and press dw. That will clear all spaces up to the ! at the end.
My AlignFromCursor plugin offers commands and mappings that align only the text to the right of the cursor, and keep the text to the left unmodified. So, with the cursor in the whitespace left of the trailing !, you can align it with <Leader>ri.

vim: delete the first 2 spaces for multiple lines

What's the easiest way to delete the first 2 spaces for each line using VIM? Basically it's repeating "2x" for each line.
Clarification: here the assumption is the first 2 characters are spaces. So the question is about doing indentation for multiple lines together.
Enter visual block mode with Ctrl-V (or Ctrl-Q if you use Ctrl-V for paste);
Select the area to delete with the arrows;
Then press d to delete the selected area.
Press Esc
Some more options. You can decided which is the "easiest way".
Remove the first 2 characters of every line:
:%normal 2x
Remove first 2 characters of every line, only if they're spaces:
:%s/^ /
Note that the last slash is optional, and is only here so that you can see the two spaces. Without the slash, it's only 7 characters, including the :.
Move indentation to left for every line:
:%normal <<
You could also use a search and replace (in the ex editor, accessed via the : character):
Remove first two characters no matter what:
%s/^.\{2}//
Remove first two white space characters (must be at the beginning and both must be whitespace... any line not matching that criteria will be skipped):
%s/^\s\{2}//
Assuming a shiftwidth=2, then using shift with a range of %
:%<
Two spaces, or two characters? (2x does the latter.)
:[range]s/^ //
deletes two blanks at the beginning of each line; use % (equivalent to 1,$) as [range] do to this for the entire file.
:[range]s/^..//
deletes the first two characters of each line, whatever they are. (Note that it deletes two characters, not necessarily two columns; a tab character counts as one character).
If what you're really doing is changing indentation, you can use the < command to decrease it, or the > command to increase it. Set shiftwidth to control how far it shifts, e.g.
:set shiftwidth=2
I'd try one of two approaches:
Do column editing on the block to delete using Ctrl+V (often mapped to Ctrl+Q).
Record a macro on the first row using q1 (or any other number/letter you want to denote the recording register), then replay that macro multiple times using #1 (to use my previous example. Even better, use a preceding number to tell it how many times to run - 10#1 to run that macro 10 times, for example. It does, however, depends on what you recorded - make sure to rewind the cursor 0 or drop one line j, if that's relevant.
I'd also add: learn how to configure indentation for vim. Then a simple gg=G will do the trick.

Resources