1

I'm writing Python programs using Vim/NeoVim. One thing I often do is copying text to the system clipboard using "+y command. This lets me copy parts of the program to the clipboard, and run it in a Python interpreter to check for errors. This method does not work always work reliably if there is an indented block of code that contains any empty lines. For example, consider the following Python code snippet in Vim:

for i in range(0, 100):
    print(i)

    print('**')

Note the empty third line. If you were to run the command "4+yy while the cursor was at the first line, it would copy the four lines to the system clipboard. But when you paste it to a Python interpreter, you'll get an IndentationError: unexpected indent error. This is because Python begins the execution of an indented code when it encounters two consecutive new lines. In this case, first two lines are executed after encountering the empty line, while the fourth line is inserted to the interpreter with an indent, hence the IndentationError.
I could avoid this issue if there was a method to tell Vim not to copy empty lines. Is there a way to tell Vim not to copy new lines?

1
  • Rather than manually copying/pasting chunks of code into Python, I recommend trying out a plugin that sends the text over for you. There're a bunch of them; I use vim-slime.
    – Rich
    Aug 21, 2023 at 10:13

3 Answers 3

1

I tried the following. Now I personally think this is a big hack and shouldn't really be used, but since you haved asked for, how about the following:

func! DropEmptyLinesOnYank()
    if v:event.regname == 'a'
        let reg_new=filter(copy(v:event.regcontents), '!empty(v:val)')
        call setreg('a', reg_new, v:event.regtype)
    endif
endfunc

augroup MyTextYankedGroup
    au!
    au TextYankPost * :call DropEmptyLinesOnYank()
augroup end

This assumes, you want to drop empty lines only when yanking into the a register. Not sure if this is what you want. But from a short testing, this seems to work. Note: the v:event variable is read-only, you are not allowed to change it, that's why I had to use the setreg() instead.

0

I would:

  • Select the lines to copy
  • Delete the empty lines: :'<,'>g/^$/d
  • Select the the block: gv
  • Copy the lines: y
  • Restore the empty lines: u

Remark: If you are using the IPython console it is much better at guessing the end code block and you'll probably not have to delete the white lines before pasting anymore (at least it works fine for the example you have provided).

7
  • Using undo would mess with the undo history. OP: If I understand your usecase correctly, I suggest writing a function that sends the visually-selected text to the embedded terminal buffer. You can then tweak the visually-selected text in that function, a/c to filetype etc. I have two such functions, one to send to tmux pane and another to send to neovim's terminal buffer.
    – 3N4N
    Aug 21, 2023 at 9:17
  • 2
    It's got rough edges; can't be used as plug-and-play. But if you wanna take inspiration and tweak it to your workflow, here is the link: github.com/3N4N/dotfiles/blob/…, github.com/3N4N/dotfiles/blob/…
    – 3N4N
    Aug 21, 2023 at 9:18
  • 1
    @3N4N that sounds more like an answer than a series of comments :)
    – D. Ben Knoble
    Aug 21, 2023 at 12:57
  • I would've added an answer, but right now I can't smooth out my function for general use.
    – 3N4N
    Aug 21, 2023 at 13:10
  • 1
    you could perhaps make use of a TextYankPost autocommand, that "fixes"/changes your register value. Sep 27, 2023 at 12:30
0

The Solution to your Problem is not to remove the empty lines , which may cause Problems later.
The Solution is to indent the syntactic empty lines to the Correct level.

Eg , when your Python Script has triple quotes around a string with embedded blank new lines , then you want that string to not change.
In case you use some trick to remove those empty lines during copying , you will be copying modified strings.
The trick will not only remove the syntactic blank new lines , it will also remove the embedded new lines in your string.

Instead , if you had set the editor to indent syntactic new lines , without using the trick to remove empty lines , then when you copy , your string will be unchanged & pasting will work too due to Correct indentation.

There are too many ways to achieve the indentation of empty lines , which I need not repeat here. The following articles are enough , to choose a method of your liking :

Automatically indent at the right level when moving to a completely empty line
https://vim.fandom.com/wiki/Get_the_correct_indent_for_new_lines_despite_blank_lines
https://superuser.com/questions/120754/how-do-i-make-vims-autoindent-not-drop-trailing-spaces
https://stackoverflow.com/questions/7413036/stopping-vim-from-removing-indentation-on-empty-lines

2
  • Are you suggesting to leave "blank" lines with (4*n) spaces in them? That would definitely work for the REPL, but in review I would wonder why the program text had trailing spaces like that.
    – D. Ben Knoble
    Aug 28, 2023 at 13:08
  • (1) Compared to JavaScript libraries ( KB , MB range ) loading unnecessarily in Web tools , those spaces are not much. (2) My Suggestion is not unheard of , @D.BenKnoble , It might even be "Common Practice" with some users [ stackoverflow.com/questions/2727988/…. ] [ vi.stackexchange.com/questions/36696/… ] though it is not universal.
    – Prem
    Aug 28, 2023 at 14:37

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.