124

The standard J command for joining lines replaces the newline character(s) with a space. It's useful when editing 'literature' but can be troublesome if I, say, edit a hex dump by hand if I forget to remove the superfluous space.

Is there a quick & easy method to join two lines without producing a space between them?

0

5 Answers 5

150

The gJ mapping does this; from :help gJ:

Join [count] lines, with a minimum of two lines. Don't insert or remove any spaces.

You could rebind it to J, if you want to save a keystroke:

:nnoremap J gJ

Note that this doesn't remove any spaces, so if either the current line ends with a space or next line starts with one or more spaces they will be left as is; so this:

Hello
    world

Becomes:

Hello    world

We could use Jx in this case, then it will be Helloworld, but that won't work in all cases; from the help:

Join the highlighted lines, with a minimum of two lines. Remove the indent and insert up to two spaces

[...]

These commands, except "gJ", insert one space in place of the unless there is trailing white space or the next line starts with a ')'.

So in some cases more than one space or no space is inserted. As far as I can see, there is no easy way to change this behaviour; I created a function to modify gJ to always join without spaces:

" Like gJ, but always remove spaces
fun! s:join_spaceless()
    execute 'normal! gJ'

    " Remove character under the cursor if it's whitespace.
    if matchstr(getline('.'), '\%' . col('.') . 'c.') =~ '\s'
        execute 'normal! dw'
    endif
endfun

" Map it to a key
nnoremap <Leader>J :call <SID>join_spaceless()<CR>

If you want, you can add let save = winsaveview() at the start of the function, and call winrestview(save) at the end to prevent the cursor from moving (but the current behaviour is the same as gJ).

See also: :help J, :help 'joinspaces'

4
  • Is it possible to use some "Preserve" function to keep the cursor position when using this function or how do I get this result? Commented Dec 15, 2017 at 12:19
  • Very late reply @SergioAraujo, but yeah, you can use let save = winsavesave() at the start, and winrestview(save) at the end. Commented Apr 11, 2020 at 11:33
  • normal! "_dw would prevent the deleted whitespace from stomping your @" register. Execute doesn't seem necessary for the two normal commands. Thanks for this answer!
    – idbrii
    Commented Feb 15, 2022 at 18:22
  • Unfortunately does not work from visual mode with multiple lines selected, only the last line join will have spaces removed :/
    – bew
    Commented May 9, 2022 at 22:11
13

Another trick you may try is to use replace. Sometimes this might be useful.

%s/$\n//g

Scenario: Delete the last character and join with the next line:

%s/=$\n\(.\)/\1/g

For example,

xxxx=
123

becomes:

xxxx123
5

To always join with a single space :

nmap J gJi <ESC>ciW <ESC>

To join with no space at all (removes trailing+leading space) :

nmap <C-J> gJi <ESC>diW
2
  • 1
    Welcome to this site! Your mappings look a bit over-engineered to me, it would be helpful if you could add a bit more explanations about how they work.
    – statox
    Commented Apr 9, 2019 at 15:31
  • gJ joins the lines, bringing leading whitespace with them: Hello| world (the cursor is after Hello) Then i <ESC> enters insert mode, inserts a space, then escapes back to normal mode. Then ciW <ESC> is the "change in word" command, followed by a space, which replaces all the whitespace after the cursor, then escapes back to normal mode. Hello world Commented Feb 26, 2023 at 0:37
4

Create a macro and reuse it:

qaJxq

Now replay the macro, a by using @a wherever you want to join two lines with no space.

@@ will repeat the previous macro. So you can just hold @ to join multiple lines.

4
  • 1
    Why type @a when you can type Jx? Same number of key presses and SHIFT presses!
    – Shahbaz
    Commented Jan 19, 2017 at 1:37
  • 2
    @Shahbaz Maybe because of the last line: "you can just hold @"
    – muru
    Commented Jan 19, 2017 at 3:13
  • 1
    @muru, that's true!
    – Shahbaz
    Commented Jan 19, 2017 at 15:23
  • 8
    It also makes it a repeatable command, so you can use 3@a to join 3 lines, whereas doing 3Jx would join 3 lines with spaces and then delete the space between the second and third lines, leaving spaces between the other lines.
    – Haegin
    Commented Feb 27, 2017 at 18:05
2

Select the lines you'd like to merge, enter an Ex command by typing a colon : in normal mode. Then type this command:

s/$\n\s*//gc

The entire command should look likewise:

:'<,'>s/$\n\s*//gc

This is actually a tweaked version of the @insidepower's command that replaces space-indentations as well as newline characters.

Explanation:

  • '<,'> means that we modify only the lines selected in visual mode.

  • /$\n\s* is a regex pattern. We're looking for a match that ends $ with a new line character \n and has non-determined number of whitespaces * thereafter.

  • s/pattern//gc is a substitute command to find each pattern and replace it with an empty character on confirmation.

To figure out more about flags and metacharacters for regular expressions in Vim take a look at this chapter of Vim Reference.

3
  • 2
    Hi ubique, welcome to Vi and Vim! You've got a pretty well-written answer there; kudos for that. My one nitpick is that vim regular expressions =/= python regular expressions, and sometimes that is confusing for users. Maybe link to the help document for Vim regex instead?
    – D. Ben Knoble
    Commented Oct 8, 2019 at 2:07
  • 2
    Second nit: the answer you reference was written by @insidepower and edited by Peter.
    – D. Ben Knoble
    Commented Oct 8, 2019 at 2:08
  • This solution is almost perfect! add :keeppatterns before to keep the search untouched. Also it joins 1 line too much compared to J in visual mode, apart from that it's great!
    – bew
    Commented May 9, 2022 at 21:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.