Concatenating numbers in vim - vim

i have a series of hexadecimal numbers as shown below in colums.
cdef
89ab
4567
0123
I would want to arrange the numbers in one single row starting from the last row as follows.
i.e 0123456789abcdef. How can i get it done in vim without using macros?

The commands
Reverse the lines with
:g/./m 0
Join all the lines and the ! flag does not insert or remove white-space.
:%j!
The Explanation
The :global command takes the form: :g/{pat}/{cmd}. So run command {cmd} on ever line that matches pattern {pat}. In this case our pattern is . which matches a non empty line. Our command is :move. The :move {address} command will move a whole line to an address/line, {address}. In our case we are moving each line to the top of the file so we use 0.
All together the :g/./m0 will take every non empty line and move it to the top. Since the :global command runs from the top of the file to the bottom, the first line gets moved to the top first and the last line get moved to the top of the file last. Think of this kind of like a stack (LILO). Therefore the lines are reversed.
Now all that is left is the join all the lines together with out any extra white space. The :join command takes the form :{range}join[!]. We want to join from the first line, 1, to the last line, $, so our range would be 1,$. However this is very common so there is a shortcut for this range, %. The optional ! flag tells :join to not add or remove any white space. All together :%j! will concatenate the lines into one long line.
As a side note is probably more common to reverse the lines via :g/^/m0 as the ^ pattern matches every line not just non-empty lines.
For more help see:
:h :g
:h :m
:h :j

with Join plugin (https://github.com/sk1418/Join) you could just do:
:%J '' r
or
:J '' 4 r
r flag means join lines in reverse
to achieve the goal. It supports more features regarding line joining. check it out..
and.... that script was written by me. :P

Kent's plugin does the job and is recommended if you need to do this often; here's a (more long-winded) alternative with built-in commands:
First, use the :move command together with :global to reverse the lines.
:1,4g/^/m0
Then, join without any separator:
:1,4j!

Related

Vim replacing in inverse direction

How can I replace in Vim from current line in inverse direction (upward) (for searching I'm using ?textToFind, for replacing from current position :,$s/a/b)?
You can use backwards range with :s command.
If you want to do replacement from line 1 to your current line, you can do :,1s/foo/bar/g vim will ask you if you are sure to apply command on a backwards range, press y
You can also do something like :,-3s/foo/bar/ to do replacement from current line (n) till line n-3
The range used for s// (and other Ex commands) can be made of:
line numbers, 1,23
relative lines, -5,+17
line shortcuts, .,$
marks, 'a,'g
searches, ?foo?,/bar/
or any combination of the above items, ?foo?,'g, 23,$, +5,/bar/, .,/baz/+6…
A range extending from the first instance of foo before the cursor to the last line could look like that:
?foo?,$
A range extending from the first instance of foo before the cursor to the current line could look like that:
?foo?,.
and even be shortened to:
?foo?,
There's no built-in way to visit the lines from the end to the beginning. Vim will issue a Backwards range given, OK to swap? query, and turn around the range if confirmed. The only way is by manually specifying the individual lines in reverse order:
:.s/a/b | .-1s/a/b | .-2s/a/b | ...
Of course, you can write a custom command for that.
If you also require reverse replacement inside a line (all of that only makes sense with the confirm flag, doesn't it?), you're out of luck with :substitute.

Vim: delete empty lines around cursor

Suppose I'm editing the following document (* = cursor):
Lions
Tigers
Kittens
Puppies
*
Humans
What sequence can I use to delete the surrounding white space so that I'm left with:
Lions
Tigers
Kittens
Puppies
*
Humans
Note: I'm looking for an answer that handles any number of empty lines, not just this exact case.
EDIT 1: Line numbers are unknown and I only want to effect the span my cursor is in.
EDIT 2: Edited example to show I need to preserve leading whitespace on edges
Thanks
Easy. In normal mode, dipO<Esc> should do it.
Explanation:
dip on a blank line deletes it and all adjacent blank lines.
O<Esc> opens a new empty line, then goes back to normal mode.
Even more concise, cip<Esc> would roll these two steps into one, as suggested by #Lorkenpeist.
A possible solution is to use the :join command with a range:
:?.?+1,/./-1join!
Explanation:
[range]join! will join together a [range] of lines. The ! means with out inserting any extra space.
The starting point is to search backwards to the first character then down 1 line, ?.?+1
As the 1 in +1 can be assumed this can be abbreviated ?.?+
The ending point is to search forwards to the next character then up 1 line, /./-1
Same as before the 1 can be assumed so, /./-
As we are using the same pattern only searching forward the pattern can be omitted. //-
The command :join can be shorted to just :j
Final shortened command:
:?.?+,//-j!
Here are some related commands that might be handy:
1) to delete all empty lines:
:g/^$/d
:v/./d
2) Squeeze all empty lines into just 1 empty line:
:v/./,//-j
For more help see:
:h :j
:h [range]
:h :g
:h :v
Short Answer: ()V)kc<esc>
In normal mode, if you type () your cursor will move to the first blank line. ( moves the cursor to the beginning of the previous block of non-blank lines, and ) moves the cursor to the end (specifically, to the first blank line after said block). Then a simple d) will delete all text until the beginning of the next non-blank line. So the complete sequence is ()d).
EDIT: You're right, that deletes the whitespace at the beginning of the next non-blank line. Instead of d) try V)kd. V puts you in visual line mode, ) jumps to the first non-blank line (skipping the whitespace at the beginning of the line), k moves the cursor up one line. At this point you've selected all the blank lines, so d deletes the selection.
Finally, type O (capital O) followed by escape to crate a new blank line to replace the ones you deleted. Alternatively, replacing dO<Escape> with c<Escape> does the same thing with one less keystroke, so the entire sequence would be ()V)kc<Esc>.
These answers are irrelevant after the updated question:
This may not be the answer you want to hear, but I would make use of ranges. Take a look at the line number for the first empty line (let's say 55 for example) and the second to last empty line (perhaps 67). Then just do :55,67d.
Or, perhaps you only want there to ever be one empty line in your whole file. In that case you can match any occurrence of one or more empty lines and replace them with one empty line.
:%s/\(^$\n\)\+/\r/
This answer works:
If you just want to use normal mode you could search for the last line with something on it. For instance,
/.<Enter>kkVNjd
I didn't test so much, but it should work for your examples. There maybe more elegant solutions.
function! DelWrapLines()
while match(getline('.'),'^\s*$')>=0
exe 'normal kJ'
endwhile
exe 'silent +|+,/./-1d|noh'
exe 'normal k'
endfunction
source it and try :call DelWrapLines()
I know this question has already been resolved, but I just found a great solution in "sed & awk, 2nd Ed." (O'Reilly) that I thought was worth sharing. It does not use vim at all, but instead uses sed. This script will replace all instances of one or more blank lines (assuming there is no whitespace in those lines) with a single blank line. On the command line:
sed '/ˆ$/{
N
/ˆ\n$/D
}' myfile
Keep in mind that sed does not actually edit the file, but instead prints the edited lines to standard output. You can redirect this input to a file:
sed '/ˆ$/{
N
/ˆ\n$/D
}' myfile > tempfile
Be careful though, if you try to write it directly to myfile, it will just delete the entire contents of the file, which is clearly not what you want! After you write the output to tempfile, you can just mv tempfile myfile and tada! All instances of multiple blank lines are replaced by a single blank line.
Even better:
cat -s myfile > temp
mv temp myfile
cat is awesome, yes?
Bestest:
If you want to do it inside vim, you can replace all instances of multiple blank lines with a single blank line by using vim's handy feature of executing shell commands on a range of lines within vim.
:%!cat -s
That's all it takes, and your entire file is reformatted all nice!

Vim: substitution in a range that is less than a line

Let's say I have the following line of code:
something:somethingElse:anotherThing:woahYetAnotherThing
And I want to replace each : with a ; except the first one, such that the line looks like this:
something:somethingElse;anotherThing;woahYetAnotherThing
Is there a way to do this with the :[range]s/[search]/[replace]/[options] command without using the c option to confirm each replace operation?
As far as I can tell, the smallest range that s acts on is a single line. If this is true, then what is the fastest way to do the above task?
I'm fairly new to vim myself; I think you're right about range being lines-only (not 100% certain), but for this specific example you might try replacing all of the instances with a global flag, and then putting back the first one by omitting the global -- something like :s/:/;/g|s/;/:/.
Note: if the line contains a ; before the first : then this will not work.
Here you go...
:%s/\(:.*\):/\1;/|&|&|&|&
This is a simple regex substitute that takes care of one single not-the-first :.
The & command repeats the last substitute.
The | syntax separates multiple commands on one line. So, each substitute is repeated as many times as there are |& things.
Here is how you could use a single keystroke to do what you want (by mapping capital Q):
map Q :s/:/;/g\|:s/;/:<Enter>j
Every time you press Q the current line will be modified and the cursor will move to the next line.
In other words, you could just keep hitting Q multiple times to edit each successive line.
Explanation:
This will operate globally on the current line:
:s/:/;/g
This will switch the first semi-colon back to a colon:
:s/;/:
The answer by #AlliedEnvy combines these into one statement.
My map command assigns #AlliedEnvy's answer to the capital Q character.
Another approach (what I would probably do if I only had to do this once):
f:;r;;.
Then you can repeatedly press ;. until you reach the end of the line.
(Your choice to replace a semi-colon makes this somewhat comfusing)
Explanation:
f: - go to the first colon
; - go to the next colon (repeat in-line search)
r; - replace the current character with a semi-colon
; - repeat the last in-line search (again)
. - repeat the last command (replace current character with a semi-colon)
Long story short:
fx - moves to the next occurrence of x on the current line
; repeats the last inline search
While the other answers work well for this particular case, here's a more general solution:
Create a visual selection starting from the second element to the end of the line. Then, limit the substitution to the visual area by including \%V:
:'<,'>s/\%V:/;/g
Alternatively, you can use the vis.vim plugin
:'<,'>B s/:/;/g

Specifying position for a command in Ex mode

I want to remove percentage marks from the following lines:
oh_test_() ->
[
%{"fold", ?_test(fold(ns()))},
%{"fold nested", ?_test(fold_nested(ns()))},
%{"push arg empty table", ?_test(push_arg_empty_table(ns()))},
%{"push arg table 1", ?_test(push_arg_table1(ns()))},
%{"push arg nested table", ?_test(push_arg_nested_table(ns()))},
%{"multicall 0", ?_test(multicall_0(ns()))},
%{"multicall 1", ?_test(multicall_1(ns()))},
%{"multicall 2", ?_test(multicall_2(ns()))}
].
Cursor is on the line with first %.
:,/%/s/%//
Or:
:,/%/normal ^x
Expected: all percent marks removed. Result: removes only first two percent marks.
Why?
How should I do it
Without using visual mode, and
Not counting line numbers?
Question 1:
Your range: ,/%/ is roughly translated starting from the current line. The end of the range will be the next line that matches /%/ after the current cursor line. This will yield the 2 lines. See :h :, for more information.
Question 2:
There are many ways to do accomplish this. You have already presented a normal and a s/// method. One way to fix your commands is to adjust the range. One of the following will work:
,/\]\./-1 match the ending ]. and then subtract a line
,/^\s*%\(.*\n\s*%\)\#!/ Use a negative look ahead to search for a line that does not start with a %.
All together you could use:
:,/\]\./-1s/%//
:,/^\s*%\(.*\n\s*%\)\#!/s/%//
:,/\]\./-1norm ^x
:,/^\s*%\(.*\n\s*%\)\#!/norm ^x
An alternative to using a macro. The nice thing about using macros in this case is that when an error occurs it stops. Basically you record a macro to search for the % and then delete it then move to the next line. Execute this macro a large number of times. When a % cannot be found the macro will stop.
qq0f%xjq999#q
The macro is my preferred method in this case as I do not need to do any crazy patterns or go looking for the end of the block.
If you allowed the use of visual mode I would suggest vi]k:norm ^x
For more information see:
:h range
:h :,
:h /\#!
:h q
:h #q
:h i]
You first example is basically saying... from my current position until the next % issues the command s/%//...
What you may want to do is something like
:,$ s/%//
which says, for each line from my current position till the end of the file ($), issue the command s/%//
If you didn't want to do it till the end of the file then you could
:set number
Which will show you line numbers, then do something like
:2,8 s/%//
which just issues the command for all lines from 2-8
You seem to be using :,/%/ in a way that should use :g/%/. You could use your command as such: :g/%/s/%// or :g/%/norm f%x
See :help :g for more information on the "global" command. This basically executes a command-mode command on lines matching the pattern. Your version, :,/%/ operates from the current line until the match of "%". This removes the first two because the current line has one and you're searching to the line that has one (the next line). You can read more about this in :help :range. A better way to use this option would be to use a search item that's only on the last line. For example, :,/]/s/%// or :,/]/norm f%x.

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).

Resources