Программист
0,0
рейтинг
17 августа 2013 в 09:30

Разработка → Сверхбыстрое копирование\вставка фрагментов кода

Постоянно программируя на C++/Qt, я заметил, что было бы удобнее хранить где-нибудь свои отрывки кода и иметь к ним быстрый доступ. Конечно же, я принялся искать и нашёл множество готовых программ-органайзеров и сайтов. Я перепробовал их, но меня всё это не устроило.

Хотелось именно быстрого доступа — а значит по глобальным хоткеям. Чтобы нажал — ввёл слова в поиск — получил код. Но такими функциями обладали всего две программы, а они были платными и не кроссплатформенными.

Поэтому я взялся написать свою программу на Qt. Она оказалась настолько удобной, что я уже не представляю свой кодинг без неё и конечно же решил её опубликовать — вдруг кому ещё пригодится? Под катом расскажу о проблемах и задачах, которые пришлось решить, выложу свой опыт, а также обзор самой программы и её исходного кода.


История разработки

Для начала я решил — программа должна быть, маленькой, удобной и шустрой. А значит — следует поместить программу в трее, чтобы не мешалась на панели задач. Благо что Qt предоставляет для этого удобное кроссплатформенное решение в виде класса QSystemTrayIcon. Также программа должна обязательно работать на глобальных хоткеях. Вот тут возникла проблема! Дело в том, что Qt, к сожалению, из коробки не поддерживает их. На то есть библиотека libqxt, которую я весьма успешно использовал почти год под Qt 4.8. Однако под Qt 5 её по неясной мне причине ещё нормально не доработали (на тот момент) и под Win7 она собираться ну никак не хотела — и я бросил эту затею. Вместо этого вставил самую капельку нативного кода — вызов winApi функции RegisterHotKey. Это единственная нативная вставка в программе — и я думаю что будет совсем легко доработать её под Linux или Mac.

Сами куски кода я решил сохранять в XML-базе данных. Может это и не лучшее решение, но оно пока вполне справляется с задачей. Да и вообще привык я к нему.

В качестве основы для редактора я взял, конечно же, QTextEdit. Тут меня ждал приятный сюрприз — код, скопированный из QtCreator — копируется как HTML с разметкой, а следовательно — с подсветкой синтаксиса. Тут же необходимость писать встроенную подсветку синтаксиса для C++\Qt отпала сама по себе. QtCreator имеет очень крутую подсветку синтаксиса, особенно если её настроить под себя.

Далее, когда уже была возможность вставить в окошко код и он уходил в базу, а затем в файл xml, встал вопрос о том, как его удобно и быстро получить. Для этого я написал маленький поисковик, который ищет куски кода, где встречаются все слова, указанные через пробел. Пока его вполне хватает. В моей личной базе уже около 100 фрагментов кода и всё равно среди них я отлично ориентируюсь.

Также сделал кейворды. Ну как же без них? Поиск идёт не только по основному коду, но и по ним тоже. В кеях можно указать языки программирования, к которым относится данная паста, например «c++,qt» или «qml,js». Если в результате поиска появились фрагменты кода из нескольких языков, можно дифференцировать их, добавив ключевое слово-язык.

Дорабатывая программу, нарисовал в GIMPe логотип — фигурные скобочки. Просто и понятно.

Обзор программы

Можете скачать Windows-дистрибутив программы здесь или собрать её из исходников, скачав их с github. Только распаковывайте их не на рабочий стол, как это делают многие. Дистрибутив вместе со всеми dll весит 16 МБ в запакованном виде и 40 в распакованном — Qt5 значительно разжирел и даже простейшая программа требует тащить за собой целую массу библиотек. Но я думаю что это не проблема, тем более что оно никак не сказывается на скорости работы программы.

Распакуйте программу в любую папку на диске и запустите. Она создаст в своей папке файл конфигурации config.xml, а потом, при сохранении, чистую базу данных для вашего кода base.xml. Собственно как выглядит главное меню — вы можете увидеть на скрине в заголовке статьи. Интерфейс программы пока что весь на английском, чтобы не было проблем со сборкой на некоторых системах — сообщения и подписи пока-что в исходниках.

Добавление нового фрагмента кода осуществляется по глобальному хоткею ctrl+D, а поиск — по win + V. Вы можете бросить в меня камень за такие «глобальные» хоткеи, но эксперименты показали что они самые удобные. Да, возможно вы привыкли по ctrl+D отправлять код из QtCreator куда-либо. Если это так критично, можете зайти в конструктор класса CodePaster и поменять там хоткеи на те, которые вам угодны. В дальнейшем это можно будет сделать через GUI.

Продолжим. Допустим, вы написали какой-то удобный алгоритм, или освоили новую конструкцию языка, которую нет желания печатать каждый раз. Вы просто выделяете ваш блок кода в вашей любимой IDE (например в креэйторе) — и копируете как обычно через ctrl+C. Тут же будет удобно и совсем рядом — не отпуская ctrl — нажать на D. Вылезет окно поверх вашей IDE — и код уже сам прыгнет в него! Программа в автоматическом режиме читает буфер обмена, вставляя из него код. Ещё тут есть ещё 2 небольшие фичи — вставляется подпись перед кодом в виде комментария "//", а также у самого кода убираются лишние отступы. Т.е. если вы скопировали его из середины программы, то он сдвинется влево до упора.

Вы просто нажимаете «OK» — и ваш код уже в базе! Более того, она тут же сохранилась на жёсткий диск, чтобы не потерять данные в случае какого-либо сбоя.

Далее — когда вам захотелось быстро скопировать этот код — нажимаете win + ctrl. Почему именно его? Мне он кажется удобным вариантом и нигде не задействован. Вы увидите маленький поисковик по коду, и уже оттуда сможете скопировать нужные вам фрагменты. Что касается самого поисковика — то у каждого куска кода есть контекстное меню. Вы можете удалить его из базы, можете отредактировать, а можете посмотреть его свойства.


Как видите, фрагменты кода разделяются через "---", у каждого есть свой id, а также мелкие плюшки — программа запоминает дату добавления и сколько раз он был скопирован.

Пришлось немного потрудиться, чтобы сопоставить некоторый блок текста внутри QTextEdit некоторому объекту Code — при обновлении поиска формируется «карта» — лист из специальных объектов, каждый из которых хранит начальную и конечную позицию в QTextEdit и указатель на объект кода, который этой области соответствует.

Между прочим — прогу можно использовать не только для кода, а вообще для любого текста. Например я весьма успешно забил туда свои почтовые ящики и телефон, копирую их когда надо. Получается что-то типа блокнота с быстрым доступом и поиском.

Примеры

Приведём простой пример использования программы — если вам вдруг понадобилось кинуть в вашей программе мессаджбокс для отладки (именно его, а не вывод qDebug) — заранее подготовив код, вы просто набираете win + V и вбиваете «mes» — этого достаточно, чтобы найти нужный кусок кода и скопировать его. Вы потратите одно нажатие хоткеев, набор 3 символов, Enter (который в дальнейшем можно будет убрать), и выделение-копирование. А теперь дайте сравним — сколько времени вы потратите, чтобы скопировать его из того же ассистанта? Даже если он на глобальном хоткее — вам придётся через выделение или клавиш получить фокус для строки поиска, ввести туда «mess», выбрать нужный класс мышкой (!), промотать вниз до того места где есть пример (если он есть) и только тогда скопировать его. Это как минимум в 2 раза дольше. Qt Assistant — это просто идеальная документация, однако для копирования-вставки постоянно используемых кусков кода он не подходит.

Какие варианты вы ещё предложите? Заходить каждый раз на сайт pastebin и искать там? Это тоже лишние задержки. Вводить в гугле по 100 раз одни и те же запросы? А ведь большинство программистов, с которыми я общался на эту тему — так и делали — они каждый раз всё гуглили. Но ведь один раз нашёл — можно сохранить в какой-нибудь «кэш» для быстрого доступа, изменив если надо — и использовать на здоровье! Этим кэшем и должна быть программа, хорошо интегрированная с системой для большего удобства.

Приведём другой пример. Я часто сижу на форуме prog.org.ru и постоянно нахожу или получаю много хороших решений разных небольших задач. Например, как с помощью QSettings добавить программу в автозагрузку Windows. Или как динамически подгрузить ui-форму. Там целые алгоритмы. Каждый раз искать то нашёл один раз — это не комфортно. Хорошие и красивые решения приятно сохранять для себя для будущего использования.

Ещё один пример — я один раз сохранил код для bat-файла, который добавляет переменную в windows environment variables. Когда он бывает нужен — просто копирую его в командную строку вместо использования неудобного GUI.

Вы конечно также можете предложить сохранять фрагменты кода в файлы, однако как только встанет вопрос о быстром доступе и поиске, а также об удобной организации таких файлов — вы увидите, что это не самое лучшее решение. Большие куски кода — целые библиотеки и классы — конечно же стоит хранить именно так, но речь идёт о маленьких фрагментах, которые мы часто используем.

Если вы работаете сразу с несколькими языками программирования — преимущества использования такой программы станут ещё более существенными. Вы можете забыть как выглядит та или иная конструкция на определённом языке — и через поиск легко вспомнить.

Обзор исходного кода

Исходный код я писал жёстко по стандарту Qt Coding Style. Временами использовал конструкции С++11. Я думаю при его чтении проблем не возникнет. Все окна построены на основе виджетов, однако потом планирую перевести их на QML.

Вообще — не судите строго. Это мой первый публичный проект и я надеюсь что хоть кому-то пригодится если не прога, то те моменты, которые я изложил здесь. Если прога окажется реально полезной и вы плюсуете — то могу её доработать. В планах — сделать её ещё удобнее (идеи есть), подсветку синтаксиса для других языков и поддержку хоткеев для Linux\Mac.

Также не исключаю, то что где-то в статье или в коде есть опечатки и\или ошибки. Рад буду принять здавую критику.

Так что — жду ваших отзывов!
Ярослав @kciray
карма
64,2
рейтинг 0,0
Программист
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Спецпроект

Самое читаемое Разработка

Комментарии (48)

  • +2
    Я слышал, что в том Qt, который сейчас в гите, уже есть поддержка глобальных хоткеев.
    • +3
      Это очень хорошо. Сделаю мою программу полностью без нативного кода
      • +2
        Недавно навелосипедил кросплатформенную библиотеку глобальных хоткеев для 5-го Qt, uglobalhotkey, лежит тут github.com/bakwc/Pastexen/tree/master/utils + последовательность хоткеев (несколько прямее чем в Qt).
        • +1
          спасибо, посмотрю
          • 0
            у меня получилось при помощи этого кода запустить под linux (XFDE, Qt 5, но думаю, оно не очень DE-зависимо), куда скинуть код, чтобы Вы переделали свою программу на основе этого и выложили на github?
        • 0
          Я правильно понимаю, что MacOS X и wayland не поддерживаются?
          • +2
            Да, к сожалению мака у меня нет. Но с удовольствием приму патчик, если кто-то напишет.
            • НЛО прилетело и опубликовало эту надпись здесь
              • 0
                И как там чинится? Потому что я как раз юзаю этот код, но вот под мак ос он уже не собирается нормально.
  • +2
    В Resharper есть удобный функционал макросов: допустим, я начинаю набирать нечто вроде dep, и оно подсказывает мне шаблон под названием dependencyProperty, который разворачивается в:
    public static readonly DependencyProperty AttachProperty = DependencyProperty.RegisterAttached(
    	"Attach",
    	typeof(bool),
    	typeof(PasswordHelper),
    	new PropertyMetadata(false, Attach)
    );
    
    public static void SetAttach(DependencyObject dp, bool value)
    {
    	dp.SetValue(AttachProperty, value);
    }
    
    public static bool GetAttach(DependencyObject dp)
    {
    	return (bool)dp.GetValue(AttachProperty);
    }
    

    Неужели для C++ нет подобных инструментов? Мне кажется, такой функционал должен присутствовать в Visual Assist X.
    Преимущества перед прямым копипастом — автоматическая подстановка макросов, например имя текущего класса, или значение некого типа по умолчанию.
    • 0
      И в Visual Assist X, и во многих редакторах есть специальные сниппеты, но они в основном для конструкций, типа fori разворачивается в цикл for по i и так далее, но тут немного другая идея — именно куски (не шаблоны) полезного и частоиспользуемого кода. Допустим код пустой кнопки на тулбаре под Ubuntu Toolkit. Мне бы очень не помешал)
      • +2
        «Кусок» — это частный случай шаблона без подставляемых элементов. И обращаться к ним с помощью intellisense, имхо, гораздо удобнее чем из стороннего приложения, даже если оно вызывается через глобальный хоткей.
        • +2
          Конечно удобнее, даже в простейшем случае вставка шаблона через ReSharper, например, попутно сократит полные имена с помощью using, отформатирует код и поставит курсор в нужное место. Да еще и будет контролировать скоуп где можно вставить этот шаблон, а где нет. Правда возможности C++ сниппетов в любой IDE к сожалению куда меньше, приходится довольствоваться тем что есть.
          • 0
            Вы мне подали отличную идею! Я напишу для CodePaster импорт и синхронизацию с нативными сниппетсами для нескольких IDE. Действительно, в некоторых случаях вводить и заменять было бы удобнее. Можно будет рядом с полем для ключевых слов добавить поле для одного слова-сокращения, при введении которого происходит автозамена. А потом уже написать конверт таких фрагментов кода в родные для IDE форматы — я думаю это не очень сложно. Или же слегка извратиться и сделать, чтобы программа отслеживала буфер и при введении ключевых слов посылала символы в активное окно. Хотя это уже извращение.

            Идея программы в том, чтобы хранить все фрагменты кода для всех языков в одном месте. А любимая IDE под рукой может быть далеко не всегда. Кроме того, вам может понадобится запомнить не кусок кода а алгоритм — например алгоритм добавления иконки для exe-шника в Qt — и его нужно просто иметь возможность быстро посмотреть — и вставить куски кода в несколько мест в несколько файлов.
            • 0
              Предлагаю еще более интересную идею — сниппеты можно загружать на сервис из программы, а потом искать по ним и скачивать. Чтобы в ней можно было при желании найти не только то, что записал сам, но и наработки других.
              • 0
                В QtCreator есть нативная функция для получения сниппетсов например с pastebin, правда не удобная. А наработки других можно откуда угодно выделить и через ctrl+D добавить без труда в базу проги, хоть из браузера, хоть из других программ. Или можно сделать экспорт в тот же pastebin
  • +1
    Отличное решение часто встречающейся задачи!
    Единственное, что хотелось бы сказать — жалко, что не под Linux первая версия, чтобы попробовать придется портировать) Мне в этот придется разобраться (а в отпуске не особо хочется, принципиально), надеюсь, кто-нибудь сделает и поделится!
    • 0
      Спасибо) Что касается линукса и мака — CodePaster в теории должен под них без проблем собраться из исходников, однако без глобальных хоткеев — работать придётся через трей — это не так удобно
  • +2
    Вы просто нажимаете «OK» — и ваш код уже в базе! Более того, она тут же сохранилась на жёсткий диск, чтобы не потерять данные в случае какого-либо сбоя.
    Мне кажется, или в вашем коде в случае сбоя во время сохранения можно потерять всё, потому что файл перезаписывается?

    Логичным было бы взять тот же SQLite, где о таких вопросах уже подумали. Или поступать как некоторые редакторы (как минимум, Vim; впрочем, это не единственный вариант): сохранять файл рядом (главное: в той же файловой системе) под другим именем, а затем заменять старый файл на новый. Альтернативный от того же Vim: делать копию старого файла, переписывать старый файл, удалять копию.
    • +3
      А зачем именно копию, почему просто не переименовать?
      • +2
        Вы про второй случай? Затем, что если использовать вариант «переименовать старый файл, записать на его место новый, удалить переименованный старый», то вы нарвётесь на проблемы с символическими ссылками (файл перестанет быть символической ссылкой). Ещё таким образом можно убрать какие‐нибудь атрибуты файла (к примеру, A: запрещает изменение информации о времени доступа к данному файлу)¹. В большинстве случаев проблему можно обойти, но обычно проще делать именно так: копия, затем перезапись.

        ¹ Я говорю именно про A, а не про что‐нибудь более известное (вроде прав на запись), именно потому что что‐нибудь более известное более известно (т.е. об этом проще вспомнить, когда вы будете писать код для обхода проблемы).
        • +1
          Резонно, спасибо!
    • 0
      Хорошо, в следующей версии исправлю этот недочёт
  • 0
    Вы бы лучше сниппеты для креатора доработали чтобы в них скрипты на js работали как в сниппетах от kate.
    • 0
      Это очень непростая задача. Хотел плагинописанием для QtCreator заняться, да всё руки никак не доходили
      • +1
        Вот аналогично, всё хочу взяться и сделать это. Да некогда.
  • 0
    Под Mac OSX есть классная программа Dash, основная фича это просмотр документации, но есть и сниппеты. Поддерживаются разные языки, подсветка, возможность вставки плейсхолдеров и управление позицией курсора после вставки из буфера обмена. Платная, но денег своих стоит.
    • 0
      Спасибо! Не думал что есть такой браузер документаций. Даже любимый Yii там есть)
  • +4
    А мне кажется, что копирование кода — сильно неправильный путь. Если есть частоиспользуемые куски кода, то их нужно вынести в библиотеку или .h-файл и таскать его в разные проекты.
    • 0
      А если я участвую в разработке каких-то крупных программ — мне и свои библиотеки в них внедрить? Работодатель далеко не всегда это одобрит.
      • 0
        Можно накопипастить из своей библиотеки в файл utils. Но это будет разовое действие, а не постоянное.
        • +1
          Это не удобно. Если кусков кода будет много, то навигация по файлу будет затруднена. Да и придётся его открытым постоянно держать.
          Во многих IDE сниппетсы не просто так же вводят. Я как-раз предлагаю их расширение и обобщение.
    • +1
      Тут важно смотреть на контекст использования. Обычно он подразумевает что мы не просто используем этот код, а сильно модифицируем его в последствии. Конечно, можно заложить всю гибкость в библиотеку, но часто гораздо разумнее вынести логику в отдельный слой, а его основу генерить относительно простыми сниппетами. Более сложным вариантом таких сниппетов будет генерация кода, например, scaffolding.
  • +3
    Да вроде такой функционал много где есть в интегрированном виде. Называется он snippets/templates. В sublime text, eclipse (С++), idea, netbeans (С++) он есть из коробки, только в Visual Studiи от MS это делается с помощью платных плагинов + к тому же как написал пользователь impwx они из коробки еще умеют:
    Преимущества перед прямым копипастом — автоматическая подстановка макросов, например имя текущего класса, или значение некого типа по умолчанию.

    А так же возможность определить параметры сниппета и быстро их заполнить после вставки.

    Ну и вообще кажется идея больше подходит для реализации как плагина, для какого-нибудь qt-creator, а не отдельного приложения.
    • +1
      Как я уже сказал в комментариях выше, можно сделать импорт в IDE-нативные сниппетсы. Но кроме сниппетсов — программа позволяет хранить заметки, последовательности действий (как вшить ресурс в exe-шник например) и т.д. — что иногда бывает очень полезно
  • 0
    Вы программируете на Qt для себя или для организации? Кучу лет уже пытаюсь устроиться куда-нибудь Qt-программистом в Донецке, но с такими вакансиями у нас беда :(
    • 0
      В данном случае программу писал для себя. Но бывает подрабатываю на фриланс-основе. Если вы хороший специалист, я думаю вы сможете найти высокооплачиваемую удалённую работу не зависимо от вашего места жительства
    • +1
      Старайтесь быть не Qt-программистом, а C++ программистом :)
      • 0
        С этим в нашем городе тоже тяжко :( Везде один Python требуется. Не в почете у нас православные языки…
  • +2
    В Emacs для этого существует yasnippet www.emacswiki.org/emacs/Yasnippet который, вроде как, позаимствован из TextMate. Но я как то так и не привык им пользоваться.
  • 0
    Я, недавно перепробовав кучу программ, гуглящихся по слову сниппеты, остановился на молодой и бесплатной Snippets (под вин и мак).
    Техподдержка, кстати, понимает по-русски, с радостью приняла к сведению мои пожелания об улучшении программы.

    Как там насчёт поддержки глобальных клавиш не знаю, для навигации в ней пользуюсь мышкой.
    • +1
      Действительно это очень хорошая программа — в ней есть даже поиск и глобальные хоткеи. Однако отсутствие поддержки линукса и исходных кодов меня не радует. Хотя программа чем-то лучше моей, да. Но поскольку CodePater на Qt основан, его можно будет под Linux портировать без проблем вообще.
      Взял несколько идей на заметку. В частности, вызов сниппетса по alt+space — хорошая идея.
  • +1
    Вопрос ко всем — стоит ли потом, когда мы качественно доработаем эту программу и учтём все пожелания в комментариях, писать вторую статью типа «Сверхбыстрое копирование\вставка фрагментов кода — часть 2»?
    • +2
      Стоит!
      • +1
        Хорошо, спасибо за поддержку, напишу, когда хорошенько доработаем прогу
  • 0
    Было бы круто, если бы прога умела привязываться к github gist
    • 0
      Можно туда экспорт сделать. Правда я не знаю где это может пригодится
  • 0
    Ссылка на программу под Windows битая, при попытке перейти по www.filedropper.com/codepaster10 происходит редирект на www.filedropper.com/.

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.