Вставка из буфера обмена в оболочку zsh или bash с поддержкой vi

15

Я хотел бы иметь возможность вставлять из системного буфера обмена (или выделения текста) в мою "vi-like" оболочку с помощью клавиатуры. Я обычно использую zsh и иногда bash. В обоих случаях у меня установлена ​​оболочка с vi-подобным поведением ( bindkey -v/ set -o vi).

В vim поведение, которое я ищу, доступно с последовательностью клавиш "+p. Эта конкретная последовательность клавиш не работает должным образом в приглашении оболочки с поддержкой vi. Есть ли способ включить это или похожее поведение, используя только клавиатуру, оставаясь с привязками клавиш в стиле vi в приглашении оболочки zsh или bash?

-- редактировать --

Случай использования: Я часто перемещаюсь между Firefox с помощью дополнения Pentadactyl , эмулятора терминала и самого vim - используя оконный менеджер Xmonad с настраиваемыми клавишами для перемещения. Все три программы имеют привязки клавиш в стиле vi, что очень эффективно (для «памяти пальцев»), поэтому было бы идеально передавать текст между ними, используя только синтаксис vim (или очень похожий синтаксис).

Dalker
источник

Ответы:

9

Zsh не поддерживает ничего, кроме внутренних регистров, а bash вообще не поддерживает регистры, насколько я знаю. В общем, оболочки поддерживают команды vi, а не команды vim.

В zsh вот подтверждение концепции доступа к выбору X из командного режима. Для реального использования вы хотели бы развить эти методы. Я использую xselпрограмму, вы можете использовать xclipвместо этого; смотрите Как скопировать из одного экземпляра vim в другой, используя регистры . Вы найдете функции, которые я использовал в руководстве по zle .

vi-append-x-selection () { RBUFFER=$(xsel -o -p </dev/null)$RBUFFER; }
zle -N vi-append-x-selection
bindkey -a '^X' vi-append-x-selection
vi-yank-x-selection () { print -rn -- $CUTBUFFER | xsel -i -p; }
zle -N vi-yank-x-selection
bindkey -a '^Y' vi-yank-x-selection

Функция vi-append-x-selectionвставляет текущий выбор X после курсора (аналогично pили P). Функция vi-yank-x-selectionкопирует последний убитый или выдернутый текст в выборку X. zle -Nобъявляет функции как виджеты zle (т.е. команды редактирования). bindkey -aустанавливает привязки для командного режима vi.

Жиль "ТАК - прекрати быть злым"
источник
Это отлично работало после установки xselи копирования предложенного кода с небольшим изменением моего .zshrc (я выбрал «^ P» вместо «^ X», перезаписывая исходное поведение «^ P»)
Dalker
4

Вот решение для zsh (режим vi), которое оборачивает оригинальные виджеты, так что буфер обмена всегда синхронизирован

Замените xclipна ваш любимый инструмент буфера обмена.

function x11-clip-wrap-widgets() {
    # NB: Assume we are the first wrapper and that we only wrap native widgets
    # See zsh-autosuggestions.zsh for a more generic and more robust wrapper
    local copy_or_paste=$1
    shift

    for widget in $@; do
        # Ugh, zsh doesn't have closures
        if [[ $copy_or_paste == "copy" ]]; then
            eval "
            function _x11-clip-wrapped-$widget() {
                zle .$widget
                xclip -in -selection clipboard <<<\$CUTBUFFER
            }
            "
        else
            eval "
            function _x11-clip-wrapped-$widget() {
                CUTBUFFER=\$(xclip -out -selection clipboard)
                zle .$widget
            }
            "
        fi

        zle -N $widget _x11-clip-wrapped-$widget
    done
}


local copy_widgets=(
    vi-yank vi-yank-eol vi-delete vi-backward-kill-word vi-change-whole-line
)
local paste_widgets=(
    vi-put-{before,after}
)

# NB: can atm. only wrap native widgets
x11-clip-wrap-widgets copy $copy_widgets
x11-clip-wrap-widgets paste  $paste_widgets
olejorgenb
источник
Это работает как шарм в xterm-termite.
Ротарети
3

Выбор и буфер обмена - это разные вещи в X Window, и IMHO «окружение рабочего стола», как правило, делает проблему еще более мутной, чем была.

Shift-insert работает для вас? В голых X-приложениях это обязывает вставлять выделение при создании такой привязки.

AProgrammer
источник
Различный выбор и буфер обмена здесь не очень важны, решение, которое работает с одним, было бы легко адаптировать к другому. Среды рабочего стола ничего не меняют; их распространение сопровождалось смещением баланса сил от выбора к буферу обмена.
Жиль "ТАК - перестань быть злым"
shift-insert работает в моей среде, и это, безусловно, полезно знать для использования в другой системе. Однако я ищу что-то более близкое к фактическим комбинациям клавиш vim для yank и / или вставки между терминалами, самим vim и другими программами
Dalker
1

Это решение работает, если вы установили oh-my-zshи включили vi-mode плагин.

Решение Жиля xselи zleоснованное на нем решение не сработало для меня. Однако, так как я настроил vim для использования системного буфера обмена по умолчанию ( set clipboard=unnamedplusin ~/.vimrc), я просто набираю vв терминальном обычном режиме, чтобы открыть текущую команду, vimа затем я могу скопировать ее в X-буфер обмена с любой из vimкоманд yank.

joelostblom
источник
Как это связано с ZSH? Вы говорите о встроенных, :termдоступных в новых версиях Neovim и Vim?
Дорон Бехар
@DoronBehar Если у вас включен режим vi в zsh, вы можете набирать текст vв обычном режиме, чтобы редактировать набранную в настоящее время команду внутри vim, а не в окне терминала.
joelostblom
Вы должны упомянуть тот факт, что вы говорите об особенностях Neovim и Vim :termв своем ответе, иначе это не совсем понятно.
Дорон Бехар
@DoronBehar Я не говорю о :term. Однако я обнаружил, что функциональность, на которую я ссылаюсь, фактически обеспечивается oh-my-zsh. Я обновил ответ соответственно.
joelostblom