4

I am using a the vim-screen plugin that enable me to write scripts , start an interpreter in the same window and send lines the the interpreter. Problem is that the interpreter do not accept statements written on several lines.

exemple: This will work f:{[x] y:y+1; Z:y+1; :Z; };

But this won't

f:{[x] y:y+1;
    Z:y+1;
    :Z;
 };

How can I write a vim function that I could call to reshape the lines in order to be sent to the interpreter?

EDIT: I had no success in making this function, I would like to create a function that would, from a input like this (that would be visually selected)

F:{[a;b;r]
//ccc1
   aaa1;
aaa2;
  //ccc2
    aaa3;
};

output something like this F:{[a;b;r] aaa1; aaa2; aaa3; }; So I created a bounty

statquant
  • 13,672
  • 21
  • 91
  • 162
  • [This answer](http://stackoverflow.com/a/3983437/1831275) may help you – albusshin Dec 06 '13 at 09:06
  • Can you explain why Ingo's answer doesn't work? – FDinoff Dec 18 '13 at 00:52
  • Well when I am trying 1) to select 4 lines in VISUAL mode and the to do 2) `:'<,'>command! -range Invoke echomsg join(getline(1,2), '')` nothing is happening, how should I call this code ? – statquant Dec 18 '13 at 15:12
  • The idea is to define that `:command` **once**, then invoke `:'<,'>Invoke`. Obviously, choose a better name for the command itself :-) – Ingo Karkat Dec 19 '13 at 09:14

2 Answers2

6

If you want to actually modify the buffer, J / :join do that. If you just want to join the lines that are sent to the interpreter (but keep them split in the buffer), you can retrieve the selected lines with getline(), and then join() them. Here's an example command:

:command! -range Invoke echomsg join(getline(<line1>,<line2>), '')

Edit

Based on that, you can "massage" the List of lines returned by getline(). E.g. to ignore the commented lines:

:command! -range Invoke echomsg join(filter(getline(<line1>,<line2>), 'v:val !~# "^\\s*//"'), '')

Additionally strip leading whitespace (this becomes unwieldy in a single line; better use a function now):

:command! -range Invoke echomsg join(map(filter(getline(<line1>,<line2>), 'v:val !~# "^\\s*//"'), 'substitute(v:val, "^\\s\\+", " ", "g")'), '')
Ingo Karkat
  • 167,457
  • 16
  • 250
  • 324
  • There might be 50 lines... can't I use the selection ? – statquant Dec 06 '13 at 08:54
  • You can `y`ank and then `join(@", '')` the selection as well, but that doesn't take less resources, and it clobbers the register. – Ingo Karkat Dec 06 '13 at 11:20
  • `` and `` here are the boundaries of the range, not individual lines. I think that may have confused @statquant. – Randy Morris Dec 18 '13 at 01:31
  • Can someone give me an example of how to call this code I am a bit puzzled here – statquant Dec 18 '13 at 15:13
  • If your function `F:` starts at line 2 and ends with `};` in line 8, you call this with `:2,8Invoke`. – Ingo Karkat Dec 18 '13 at 15:17
  • I've added two extended variants that gets you the result from your question's edit. (The bounty provided some motivation :-) – Ingo Karkat Dec 18 '13 at 15:25
  • hey Ingo that was the purpose of it :) can't we get rid of the lines numbers so I can call it with visually selected text ? – statquant Dec 18 '13 at 22:14
  • When you press `:` in visual mode, Vim will automatically insert `:'<,'>` for you. Complete that to `:'<,'>Invoke`, and you're done. Line numbers don't have to be numerical; marks work, too! Define `:vnoremap :Invoke`, and you have a visual mode mapping for it! – Ingo Karkat Dec 19 '13 at 07:14
0

Standard continuation character in vimscript scripts is backslash in the beginning of the next line. So, this

f:{[x] y:y+1;
  \  Z:y+1;
  \  :Z;
 \ };

should work.

mcepl
  • 2,688
  • 1
  • 23
  • 38