vim

For discussion on all things (neo)vim.
walterl 2021-06-25T01:00:07.093900Z

nmap <Leader>jk <LocalLeader>e{:keys [] :as<Esc>F[ With cursor at m, turns

(defn inc-x
  [m]
  (inc x))
into
(defn inc-x
  [{:keys [] :as m}]
  (inc x))
with the cursor at the opening [. (requires vim-sexp)

๐Ÿ˜ 3
mjw 2021-06-25T02:17:18.094100Z

Nice!

berkeleytrue 2021-06-25T03:14:35.094600Z

very noice ๐Ÿ‘Œ:skin-tone-5:

2021-06-25T15:02:04.096900Z

If I have the following code:

(foo
)

2021-06-25T15:04:28.098900Z

โ€ฆand I hit J on the first line, I get (foo), which is great, but if I have this:

[foo
]
and I hit J on the first line I get [foo ] with an extra space before the closing bracket. Same with closing braces. Does anyone know how to tell vim not to add the extra space?

๐Ÿ‘€ 1
dave 2021-06-25T15:09:39.099700Z

I know this isn't 100% helpful, but parinfer behaves the way you'd want by default.

dominicm 2021-06-25T15:11:41.100600Z

@jkrasnay Use gJ instead ๐Ÿ™‚ See :help J if you scroll down a little, you'll see the info about why ) doesn't have a space.

2021-06-25T15:15:37.102500Z

gJ leaves all the leading space. I kinda want the opposite, to remove all spaces when the next line starts with ] or }

2021-06-25T15:17:18.103500Z

@dave yeah I looked at Parinfer but Iโ€™m pretty happy working with just vim-sexp. Not sure itโ€™s worth a switch just for this issue.

๐Ÿ‘ 1
dominicm 2021-06-25T15:30:06.104200Z

@jkrasnay uhh, I'm getting different behaviour from you! According to the docs, gJ should remove all the spaces.

dominicm 2021-06-25T15:30:22.104500Z

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

dominicm 2021-06-25T15:31:19.104800Z

Maybe do nmap gJ to see if anything might be interfering?

berkeleytrue 2021-06-25T15:36:52.105200Z

"doesn't insert or remove spaces"

berkeleytrue 2021-06-25T15:37:11.105700Z

doesn't that mean the whitespace is preserved from the previous line

dominicm 2021-06-25T15:37:31.106100Z

The example didn't have any whitespace ๐Ÿ˜„ Maybe we're working from a different example then.

berkeleytrue 2021-06-25T15:37:42.106400Z

maybe it's a tabs vs spaces things

berkeleytrue 2021-06-25T15:37:51.106700Z

maybe tabs are removed but spaces are not

dominicm 2021-06-25T15:38:01.106900Z

But what kind of monster would use tabs?

berkeleytrue 2021-06-25T15:39:25.107700Z

Indeed, haha.

berkeleytrue 2021-06-25T15:39:36.108Z

nope same behavior with tab infront

dominicm 2021-06-25T15:40:09.108600Z

I suspect you're right about it being a problem with leading spaces. The examples above didn't have any, so in real world it probably has leading whitespace which gJ won't touch.

berkeleytrue 2021-06-25T15:41:37.109Z

noremap J Jx seems to work

berkeleytrue 2021-06-25T15:42:11.109500Z

oh except when the next line is only whitespace it deletes the last char of the current line...

dominicm 2021-06-25T15:42:19.109700Z

https://vi.stackexchange.com/a/440 ๐Ÿ˜„

dominicm 2021-06-25T15:42:36.110100Z

Looks like you have to go into vimscript

berkeleytrue 2021-06-25T15:42:39.110300Z

well, that's just cheating

dominicm 2021-06-25T15:42:58.110600Z

I reckon you could do something with multiline regex, just for "J"

berkeleytrue 2021-06-25T15:44:32.111Z

This one works pretty well

nmap <C-J> gJi <ESC>diW

dominicm 2021-06-25T15:44:45.111200Z

:s/\s*\n\s*//

dominicm 2021-06-25T15:45:04.111400Z

(with nnoremap ofc)

2021-06-25T16:34:30.114Z

Thanks for all the ideas. It looks like itโ€™s a tricky problem to solve generally, partly because J can work with a visual selection or line count and partly because in some cases you do want the space, e.g.

[foo
   bar]
โ€ฆshould join to [foo bar]

dominicm 2021-06-25T17:12:47.115200Z

That is true ๐Ÿ™‚ So I suppose something like :s/\s*\n(\s*\[)}]]// (without actually trying it, that is)

berkeleytrue 2021-06-25T18:23:06.115800Z

I ended up maping gJ to do that whitespace removing sine I never used that keybinding normally

2021-06-25T19:34:49.116200Z

I came up with this. Seems to work pretty well:

:nnoremap J J:s/\s*\([]}]\)/\1/g<cr>:noh<cr>
:vnoremap J J:s/\s*\([]}]\)/\1/g<cr>:noh<cr>

Sigve 2021-06-28T07:38:00.121300Z

The regex seems to work. I wanted to keep the cursor position, and not put the regex in my search register so i call it in a function: fun ClojureJ() let l:line = getline('.') call setline('.', substitute(l:line, '\s*\([]}]\)', '\1', "g")) endfun nmap J J:call ClojureJ()<cr>

2021-06-29T13:57:53.122800Z

Thatโ€™s much nicer, thanks!

2021-06-29T13:58:39.123Z

I also noticed that join leaves trailing spaces after opening brackets and braces. Made this small tweak:

fun ClojureJ()
    let l:line = getline('.')
    let l:line = substitute(l:line, '\s\+\([]}]\)', '\1', "g")
    let l:line = substitute(l:line, '\([[{]\)\s\+', '\1', "g")
    call setline('.', l:line)
endfun
nnoremap J J:call ClojureJ()<cr>
vnoremap J J:call ClojureJ()<cr>

๐ŸŽ‰ 1