Небольшой лайфхак с редактированием буфера обмена

    Я часто сталкиваюсь с такой ситуацией: пишу себе спокойно текст в чем-то (скажем, письмо в веб-интерфейсе гмейла), и вдруг, в какой-то момент возникает необходимость что-то переделать… и случается раздражение. Случается оно от того что редактирование в браузере (да и много где еще) не предполагает некоторых привычных для программиста удобств, вроде автоматической замены, регулярных выражений и макросов. При этом, вроде бы и не сложно скопировать текст в буфер и отредактировать его в правильном редакторе (Vim, Emacs, ...), но очень уж не хочется отрываться от контекста и совершать какие-то телодвижения, отвлекающие от текущей задачи… И вот, я уже расставляю отступы (нумерую список, заменяю слово, ...) вручную — результат достигнут, да и времени потрачено совсем не много, но осадочек остался…

    Знакомая ситуация? Если ответ «да», в вашей операционной системе работает bash и ваша первая ассоциация к слову «редактор» это не «Microsoft Office» значит нам есть что обсудить под катом :)


    Итак, я исхожу из того, что если уж вы освоили — а тем более привыкли — к каким-то продвинутым возможностям своего редактора, то нужно постараться сделать эти возможности как можно более доступными, чтобы где бы вы ни работали с текстом, вы могли эффективно применять свои навыки.

    Самый очевидный путь решения этой задачи — просто автоматизировать ту часть последовательности действий, которая без изменений повторяется из раза в раз. У нас таких последовательностей целых две: одна в начале перехода во внешний редактор — выделить, скопировать в буфер, открыть внешний редактор, вставить; вторая в конце — скопировать в буфер отредактированное, закрыть внешний редактор, вставить текст на старое место.

    Но для начала, в связи с тем что мы собираемся автоматизировать работу с буфером обмена…

    Несколько замечаний о буфере обмена в X Window System.


    (Вначале я упомянул что сгодится любая система в которой работает bash, и это правда. Так что, если у вас мак и особенности X Window System вам параллельны — смело пропускайте эту часть)

    Во-первых, помните что клипбоард в X Window реализован очень специфично. У нас есть как минимум 3 буфера обмена — primary, secondary и собственно clipboard. В primary попадает все что вы выделите мышью, и «выпадает» по нажатию средней кнопки мыши, clipboard — это как правило Ctrl-V / Ctrl-C. Зачем нужен secondary не знает никто.

    (Ходят слухи, что, на самом деле, X Windows настолько крута, что в ней вообще может быть сколько угодно буферов обмена, и secondary — всего лишь еще один из бесконечного ряда. Я затрудняюсь даже предположить зачем это нужно.)

    Во-вторых, полезно понимать, что в каждый момент времени содержимое буфера обмена привязано к окну из которого оно было извлечено. Наверняка, эта привязка открывает много замечательных возможностей, но все они, на мой взгляд, сводятся на нет одним отвратительным неудобством: содержимое клипбоарда исчезает если закрыть программу из которой оно было скопировано.

    С учетом этих особенностей, для стабильной и предсказуемой работы с буфером обмена в линуксе я очень рекомендую пользоваться каким-нибудь «клипбоард менеджером». В состав KDE входит вполне юзабельный klipper, а пользователям Гнома я бы посоветовал утилитку parcellite (народ еще хвалит diodon, особенно те у кого Ubuntu + Unity, но я сам не пробовал). Каким бы менеджером вы не пользовались, очень полезно привыкнуть вызывать историю буфера обмена по нажатию Ctrl-Alt-C или другого сочетания клавиш. Да, и кстати, будьте осторожны с опцией «синхронизовать клипбоарды» — после ее включения, любое выделение текста будет «затирать» текущее содержимое буфера обмена, даже если вы осознанно и явно туда что-то добавили с помощью Ctrl-C.

    Собственно, рецепт


    Итак, для достижения наших целей нам потребуются: (1) средство, позволяющее глобально привязать выполнение произвольной команды к нажатию волшебной кнопки и (2) небольшой скриптик собственного сочинения.

    Что касается привязки к клавиатурным событиям — решений множество, но я не вижу причин не воспользоваться средствами встроенными в систему (и KDE и Gnome предлагают свои редакторы «быстрых клавиш»).

    Сам же скрипт, к которому мы будем привязывать событие может выглядеть так:
    1. #!/bin/bash
    2. tmp="$(mktemp)"  # создать временный файл
    3. xclip -sel clip -o > "$tmp"  # скопировать содержимое клипбоарда в созданный файл
    4. gvim -f  "$tmp"  # открыть файл в нужном редакторе (gvim - в качестве примера)
    5. cat "$tmp" | xclip -sel clip  # скопировать содержимое файла обратно в клипбоард
    6. rm "$tmp"  # удалить временный файл
    При этом, выбор конкретных утилит, конечно, может отличаться. Например, не только xclip умеет работать с буфером обмена из командной строки — вместо xclip можно использовать утилиту xsel либо менеджер клипбоарда, а если у вас мак и OS X, то там есть команды pbcopy / pbpaste.

    Теперь дело за малым — сохранаяем скрипт в ~/bin/editclip, привязываем его к нажатию на F12 (или любому другому сочетанию клавиш) — готово! Мы можем в любой момент, в любом «левом» редакторе выделить нужный фрагмент, нажать «Ctrl-C, F12» и фрагмент откроется в нужной программе, после закрытия которой, достаточно будет нажать Ctrl-V и отредактированный текст встанет на место.

    На последок еще один небольшой совет касательно X Window. К сожалению, выделение текста не является здесь внутренним делом программы. Если вы выделили текст в одном окне, а потом переключились в другое и выделили текст снова, то в исходном окне выделение может слететь (upd: а может и не слететь — в комментариях подсказывают что этому эффекту особенно подвержены проги на gtk). Это очень неприятно, потому что нам приходится либо, редактируя текст во внешнем редакторе, всячески избегать выделения (что противоестественно), либо смириться с тем что простое нажатие Ctrl-V в конце не всегда будет заменять старый фрагмент на отредактированный.

    Чтобы обойти это неудобство, я, обычно вызываю внешний редактор с помощью «Ctrl-X, F12» — при этом исходный фрагмент текста сразу удаляется и нажатие Ctrl-V в финале вставляет на его место отредактированную версию.

    Вот и все. Надеюсь этот трюк пригодится кому-нибудь.
    Share post
    AdBlock has stolen the banner, but banners are not teeth — they will be back

    More
    Ads

    Comments 28

      +4
      Всё интересно, но исходная задача решается несколько проще, если использовать расширение браузера, вызывающее нужный текстовый редактор. Для Fx такое расширение называется «It's All Text» и создаёт кнопки возле полей ввода. Один клик по кнопке (или хоткей, или в контекстном меню, если их отключили) — и можно редактировать в своём редакторе. Потом Ctrl-S (или другое сохранение файла) — и расширение переносит сохранённое обратно в поле ввода. Помогает выносить в редактор юзерскрипты и стили. Раньше (версии до 6-7) умел заносить и стили обратно, как и всё остальное, сейчас разучился, не успевает за сменой версий. Но всё остальное умеет.
        +4
        Расширение конечно удобное но не универсальное, я например пользуюсь оперой или хромом
          +1
          Наверно хорошее расширение (надо будет попробовать) но редактирование письма было только примером. Кроме фокса есть другие браузеры, а кроме браузеров есть другие программы.
            0
            Не согласен, статья полезна описанными инструментами — я например себе xNeur|puntoSwitcher напишу (автозамены там не будет, но и нафиг не надо, только по нажатию e.g. Ctrl+Break)
            0
            Если вы выделили текст в одном окне, а потом переключились в другое и выделили текст снова, то в исходном окне выделение, скорее всего, слетит.


            Как-то никогда не замечал такого поведения. Сейчас специально проверил — всё выделение остается на месте.
              0
              Для проверки выделяли в браузере? С браузером у меня тоже все ok…
                0
                О, воспроизвел — не могу выделить текст одновременно в двух GTK-приложениях (pidgin и XChat), при этом в опере, хроме, LibreOffice, скайпе выделение остается.
                  0
                  Думаете, это «фича» из gtk, а не из иксов?
                    0
                    Похоже на то, попробовал еще с несколькими GTK-приложениями — выделенный текст остается только в одном из них.
              +1
              Наверно хорошее расширение (надо будет попробовать) но редактирование письма было только примером. Кроме фокса есть другие браузеры, а кроме браузеров есть другие программы.
                0
                упс, ошибся веткой
                0
                Хотел написать подобный скрипт, так как ситуация, описанная в начале поста мне хорошо знакома.
                Только в моей задумке это выглядело бы так: выделение текста + сочетание горячих клавиш = редактор с выделенным текстом; после закрытия редактора — текст в буфере обмена.
                  +1
                  Ещё один хардкорный кроссплатформенный способ найти и заменить по регулярке.
                  Подойдет знающим JS.

                  1. ПКМ по тексту -> проверить элемент.
                  2. Смотрим где он лежит и как его найти.
                  3. Пишем заклинание в консоли…
                  window.frames.canvas_frame.contentDocument.getElementById(':7e').value =
                  window.frames.canvas_frame.contentDocument.getElementById(':7e').value.replace(/regexp/g,'replace')
                  
                  (пример, для хрома и gmail)
                    +1
                    В X помимо упомянутых Вами PRIMARY, SECONDARY и CLIPBOARD есть ещё 8 CUT-буферов. :) Всё это просто тихий ужас. При этом CUT-буферы в отличие от первой троицы «тупые» — не привязаны к программе где выделялся/копировался текст (так что их содержимое не пропадает когда эта программа выходит), но, к сожалению, в них можно хранить только текст, и только в ASCII. Так что если копи-паст русского в юникоде будет идти через один из CUTBUFFER-ов, то с некоторой вероятностью (смотря как принятые байты будет трактовать программа куда делается paste) вместо русского вставится мусор.
                      0
                      Прикольно. Я всегда знал, что X11 — это сборище странных, реликтовых ископаемых, многие из которых не дожили до сегодняшних дней и покоятся где-то на нижних уровнях, но иногда восстают из могил.
                      0
                      Для пользователей firefox + pentadactyl при редактировании текста достаточно нажать на Ctrl+i и весь текст автоматически откроется во внешнем редакторе (gvim по-умолчанию), а после закрытия редактора текст будет замещен
                        +1
                        пытаюсь адаптировать для MacOS X, скрипт переписал так:
                        1. #!/bin/bash
                        2. tmp=$(mktemp /tmp/editclip.XXXXXXXX)  # создать временный файл
                        3. echo $tmp
                        4. pbpaste > "$tmp"  # скопировать содержимое клипбоарда в созданный файл
                        5. vim "$tmp"  # открыть файл в нужном редакторе (gvim - в качестве примера)
                        6. cat "$tmp" | pbcopy # скопировать содержимое файла обратно в клипбоард
                        7. rm "$tmp"  # удалить временный файл


                        Проблема с запуском редактора — MacVim не возвращает управление после :q, так как приложение остаётся запущенным, а mvim — наоборот отдаёт управление сразу, не дожидаясь редактирования. У кого есть опыт использования MacVim в скриптах, поделитесь.
                          0
                          «сразу, не дожидаясь редактирования» — это как раз то как ведет себя gvim без "-f".
                          mvim -f не помогает?
                            0
                            да, это то, что нужно. Финальный вариант:
                            1. #!/bin/bash
                            2. tmp=$(mktemp /tmp/editclip.XXXXXXXX)  # создать временный файл
                            3. echo $tmp
                            4. pbpaste > "$tmp"  # скопировать содержимое клипбоарда в созданный файл
                            5. mvim -f "$tmp"  # открыть файл в нужном редакторе (gvim - в качестве примера)
                            6. cat "$tmp" | pbcopy # скопировать содержимое файла обратно в клипбоард
                            7. rm "$tmp"  # удалить временный файл

                            осталось только разобраться, как этот скрипт привязать к хоткею глобально.
                          0
                          Супер, спасибо, если не поленюсь — наконец-то сделаю себе puntoSwitcher (xNeur не предлагать, он у меня не завелся), отрабатывающий только по нажатию определенного сочетания клавиш.
                            +3
                            Я на bash'e так сделал
                              0
                              Спасибо.

                              Тихонько бубнит в сторону: вот же черт! И зачем ты мне это показал? Теперь не буду писать, воспользуюсь готовым решением.

                              ))))
                                0
                                А ведь так, порой, интересно изобретать собственный велосипед)))
                                  0
                                  Согласен на 100%. Поизобретать все-таки прийдется — у меня скрипт по ссылке не отрабатывает в NetBeans и skype. Специально проверил — в этих приложениях не работает копипаст через primary-буфер (выделение текста вместо Ctrl+C, средняя кнопка мыши вместо Ctrl+V)
                                    0
                                    Не совсем понял, какой именно копипаст у вас не работает в скайпе и NetBeans — ctrl-v/ctrl-c или средняя кнопка?
                            0
                            > у меня скрипт по ссылке не отрабатывает в NetBeans и skype

                            именно потому в parcellite и klipper есть опция «Synchronize clipboards». Она у меня всегда включена, за исключением того, когда я работаю в Open Office.

                            Мой скрипт для Emacs (client):
                            #!/bin/bash
                            TMPFILE=`mktemp`
                            xclip -sel clip -o > $TMPFILE
                            emacsclient -c $TMPFILE
                            cat $TMPFILE | xclip -sel clip
                            rm $TMPFILE
                            


                            Emacs всегда запушен с опцией (server-start) — отрабатывает в миллисекунды.

                            Автору спасибо за совет! Хороший хинт.
                              0
                              Не уверен что проблема phgrey решается простым включением синхронизации клипбоардов. Хотя, я тут вчитался в его комментарий и понял что я не понимаю какой именно копипаст у него не работает…

                              Кстати, я тоже раньше всегда включал синхронизацию, а потом однажды выключил и вздохнул с облегчением — оказалось что для меня она не решает никаких проблем, а наоборот, добавляет некоторые неудобства (самое существенное — невозможность выделить текст и заменить его на содержимое буфера с помощью Ctrl-V )

                              Спасибо за спасибо )
                              0
                              Похожую технику можно использовать, например, для перевода слов:

                              #!/bin/bash
                              word=$(xclip -o)
                              firefox «lingvo.yandex.ru/$word/с английского/»

                              Only users with full accounts can post comments. Log in, please.