Yank/copy selected text to clipboard in IPython Vi mode
Question:
I can’t figure out how to copy lines that I selected/highlighted in IPython in Vim mode to the normal clipboard (to be pasted outside of the IPython shell). Normally, in vim I can yank text using "+y
and paste it somewhere else, but hitting those keys in IPython Vim mode doesn’t seem to work. So I end up having to highlight the desired text using my mouse and copying it with Command-C.
This is an annoyance because if I have multiple lines in IPython there will be many junk characters that I have to filter out as seen below:
In [8]: import numpy as np
...: import math
...:
...: print("hi")
...: while(True):
...: break
...:
...: x = 3
...: y = 4
...:
...:
Here I would have to filter out the In [8]
and the ...:
on each line. But selecting using v
or V
appropriately ignores these junk characters.
This answer doesn’t say how to do it in Vi mode and also doesn’t mention anything about yanking to the system’s clipboard.
Answers:
if you are running ipython inside vim terminal, you can type the following in ipython:
%history -l 10
This will print last 10 commands without the leading dots. Which can be easily copied.
You need to open the ipython in vim terminal. And then, after typing the %history command (above), you will need to go to normal mode with key-combination Ctrl-W Shift_N
. Then, copy multiple lines using V (block visual model) into +
register with "+y
command. You can then copy it into another vim buffer using "+p
or another application such as gedit using ‘right click, then paste.’
Here is a little plug-in script I wrote for this very purpose after digging into the docs for IPython and prompt-toolkit: y
yanks to system clipboard, p
pastes after the cursor (this is different from normal vi(m) behaviour). This script is to be added to the startup
subdirectory of your IPython profile config directory (See IPython docs or example config)
#!/usr/bin/env python3
from IPython import get_ipython
from prompt_toolkit.enums import DEFAULT_BUFFER
from prompt_toolkit.keys import Keys
from prompt_toolkit.filters import HasFocus, ViNavigationMode, ViSelectionMode, ViInsertMode, EmacsInsertMode, HasSelection
from prompt_toolkit.key_binding.vi_state import InputMode
import pyperclip
ip = get_ipython()
def copy_selection_to_clipboard(event):
buffer = event.current_buffer
data = buffer.copy_selection()
pyperclip.copy(data.text)
def paste_from_clipboard(event):
buffer = event.current_buffer
data = pyperclip.paste()
event.cli.vi_state.input_mode = InputMode.INSERT
buffer.insert_text(data)
event.cli.vi_state.input_mode = InputMode.NAVIGATION
# Register the shortcut if IPython is using prompt_toolkit
if getattr(ip, 'pt_app', None):
filter_ = HasFocus(DEFAULT_BUFFER) & ViSelectionMode()
ip.pt_app.key_bindings.add_binding('y', filter=filter_)(copy_selection_to_clipboard)
filter_ = HasFocus(DEFAULT_BUFFER) & ViNavigationMode()
ip.pt_app.key_bindings.add_binding('p', filter=filter_)(paste_from_clipboard)
I just found a better way to use the system clipboard in ipython vi-mode that just works: Just use the PyperclipClipboard for prompt_toolkit:
In your ~/.ipython/profile_default/startup/keybindings.py
(or any other startup file)
from IPython import get_ipython
from prompt_toolkit.clipboard.pyperclip import PyperclipClipboard
ip = get_ipython()
if getattr(ip, "pt_app", None):
ip.pt_app.clipboard = PyperclipClipboard()
I can’t figure out how to copy lines that I selected/highlighted in IPython in Vim mode to the normal clipboard (to be pasted outside of the IPython shell). Normally, in vim I can yank text using "+y
and paste it somewhere else, but hitting those keys in IPython Vim mode doesn’t seem to work. So I end up having to highlight the desired text using my mouse and copying it with Command-C.
This is an annoyance because if I have multiple lines in IPython there will be many junk characters that I have to filter out as seen below:
In [8]: import numpy as np
...: import math
...:
...: print("hi")
...: while(True):
...: break
...:
...: x = 3
...: y = 4
...:
...:
Here I would have to filter out the In [8]
and the ...:
on each line. But selecting using v
or V
appropriately ignores these junk characters.
This answer doesn’t say how to do it in Vi mode and also doesn’t mention anything about yanking to the system’s clipboard.
if you are running ipython inside vim terminal, you can type the following in ipython:
%history -l 10
This will print last 10 commands without the leading dots. Which can be easily copied.
You need to open the ipython in vim terminal. And then, after typing the %history command (above), you will need to go to normal mode with key-combination Ctrl-W Shift_N
. Then, copy multiple lines using V (block visual model) into +
register with "+y
command. You can then copy it into another vim buffer using "+p
or another application such as gedit using ‘right click, then paste.’
Here is a little plug-in script I wrote for this very purpose after digging into the docs for IPython and prompt-toolkit: y
yanks to system clipboard, p
pastes after the cursor (this is different from normal vi(m) behaviour). This script is to be added to the startup
subdirectory of your IPython profile config directory (See IPython docs or example config)
#!/usr/bin/env python3
from IPython import get_ipython
from prompt_toolkit.enums import DEFAULT_BUFFER
from prompt_toolkit.keys import Keys
from prompt_toolkit.filters import HasFocus, ViNavigationMode, ViSelectionMode, ViInsertMode, EmacsInsertMode, HasSelection
from prompt_toolkit.key_binding.vi_state import InputMode
import pyperclip
ip = get_ipython()
def copy_selection_to_clipboard(event):
buffer = event.current_buffer
data = buffer.copy_selection()
pyperclip.copy(data.text)
def paste_from_clipboard(event):
buffer = event.current_buffer
data = pyperclip.paste()
event.cli.vi_state.input_mode = InputMode.INSERT
buffer.insert_text(data)
event.cli.vi_state.input_mode = InputMode.NAVIGATION
# Register the shortcut if IPython is using prompt_toolkit
if getattr(ip, 'pt_app', None):
filter_ = HasFocus(DEFAULT_BUFFER) & ViSelectionMode()
ip.pt_app.key_bindings.add_binding('y', filter=filter_)(copy_selection_to_clipboard)
filter_ = HasFocus(DEFAULT_BUFFER) & ViNavigationMode()
ip.pt_app.key_bindings.add_binding('p', filter=filter_)(paste_from_clipboard)
I just found a better way to use the system clipboard in ipython vi-mode that just works: Just use the PyperclipClipboard for prompt_toolkit:
In your ~/.ipython/profile_default/startup/keybindings.py
(or any other startup file)
from IPython import get_ipython
from prompt_toolkit.clipboard.pyperclip import PyperclipClipboard
ip = get_ipython()
if getattr(ip, "pt_app", None):
ip.pt_app.clipboard = PyperclipClipboard()