A simple way is this: simply select your lines (all but the last one) - or use % - and run:
:'<,'>s/\n/,/
or
:'<,'>s/\n/, /
(where, of course, the '<,'> part was already inserted after : by Vim, to target the selection)
(2nd) Update:
Building on the above (and Sato Katsura's comment), here's a possible "interactive join" implementation, with count and optional repeat support:
" ================ script ===============================================
" interactive 'J', 'gJ' replacement with optional 'vim-repeat' support
" The last used separator is automatically reused as:
" a. default choice
" b. when repeating (=> non-interactive repeats: same range, same separator)
let g:last_join_separator = " "
function! s:interactiveJoin(use_last_sep,...) range
if (a:use_last_sep == 0) "interactive, ask for separator to use
call inputsave()
echohl Question
let l:sep = input("Separator:", g:last_join_separator)
echohl None
call inputrestore()
redraw!
let g:last_join_separator = l:sep "update last separator value
else "non-interactive (when repeating with '.')
let l:sep = g:last_join_separator
endif
if (a:0 == 0) "with no argument, remove indentation *and trailing spaces*
let l:subst = 's/\s*\n\+\s*/\=' . "'" . l:sep . "'/"
else " don't remove indentation or trailing spaces (act like 'gJ')
let l:subst = 's/\n\+/\=' . "'" . l:sep . "'/"
endif
if a:firstline < a:lastline "join given range
execute a:firstline . ',' . (a:lastline - 1) . l:subst
let l:count = a:lastline - a:firstline + 1 "default count for repeat
else "or join only with next line
execute l:subst
let l:count = 1 "default count for repeat
endif
"make command repeatable
"(with the tpope/vim-repeat plugin: optional, recommended)
if (a:0 == 0)
silent! call repeat#set("\<Plug>(repeatJoin)", l:count)
else
silent! call repeat#set("\<Plug>(repeatGJoin)", l:count)
endif
endfunction
noremap <silent> <Plug>(interactiveJoin) :call <SID>interactiveJoin(0)<CR>
noremap <silent> <Plug>(interactiveGJoin) :call <SID>interactiveJoin(0,'g')<CR>
noremap <silent> <Plug>(repeatJoin) :call <SID>interactiveJoin(1)<CR>
noremap <silent> <Plug>(repeatGJoin) :call <SID>interactiveJoin(1,'g')<CR>
And an actual mapping:
"================= vimrc ================================================
nmap J <Plug>(interactiveJoin)
xmap J <Plug>(interactiveJoin)
nmap gJ <Plug>(interactiveGJoin)
xmap gJ <Plug>(interactiveGJoin)
This is kinda(*) like J, but interactive - it will prompt for the separator string. The default string is a space - so, for example, to join lines with no separator, hit Backspace when prompted, to remove the default space character, and Enter to accept the (now) empty separator. Count, e.g. 3J, also works. If tpope/vim-repeat plugin is installed, repeating with '.' will also work, reusing the last separator and (if not changed - e.g. 10.) the last count or visual line range.
(*) It's not exactly like J,though: while it will remove indentation, it won't check for .!? (end of phrase) to insert 2 spaces instead of one, or insert a space only if it's missing (it's hard to do something like this, since the separator string can be anything now). It will also remove trailing spaces (makes more sense).
I think this might be a nice way to overload the limited operators letter-space :)
Well, technically J is not quite an operator, but close to one - for example, you can't do Jaw, to join "a word".
(suggestions are welcome)

sedis more or less the same as:%s/../../? – Martin Tournoij Apr 28 '20 at 16:41