Javascript для Notepad++

    Здравствуй Храбрачеловек,

    сегодня я решил поделиться с тобой Plugin'ом для Notepad++, который позволит тебе спомощью JavaScript автоматизировать некоторые действия над текстом и не только.

    Рождение идеи


    С тех пор как я открыл для себя Notepad++, прошло довольно таки много времени. Я использую его как дома так и на работе. Иногда приходится обрабатывать рутиным образом файлы и в большинстве случаев достаточно регулярных выражений. Но бывают случаи, когда хочется немного больше логики, чтобы одним махом произвести замену или что либо подсчитать. Для полного счастья не хватает VBA :-).
    Поискав не долго я нашел Plugin под названием «Simple script». Он позволяет используя определенный набор функций последовательно обработать текст. Вообщем оказался слишком ПРОСТОЙ скрипт, чтобы удовлетворить мои в принцие на тот момент небольшие потребности. Дружба с «Simple script»
    так и не сложилась.

    По долгу службы я познакомился с Microsoft Windows Script, c помощью которого я тогда автоматизировал генерирование и обработку XML файлов. Однажды читая документацию к нему, я обнаружил, что его можно прикрутить и к своему приложению. Поискав по интернетам дальнейшую информацию и опыт внедрения в свои приложения я обнаружил законченный пример на RSDN.ru.

    Мне было ясно, что я хочу полноценный JavaScript в Notepad++ и что это возможно.

    Реализация


    Многочисленные попытки начать дело потерпели неудачу. Отсутствие ATL на домашнем компьютере, а так же отсутствие желания и времени разбираться с этой библиотекой, создавали относительно большой порог для начала. Но однажды готовясь к очередному набегу я набрел на две ключевые статьи:СОМ без ATL и Использование Скриптинг. Спомощью этих двух статей был переработан пример с RSDN.ru без использования ATL. Моему восторгу не было предела, когда заработал первый прототип.

    Довольно быстро я реализовал первоначальную идею — выполнение выделенного или скопированного в буфер обмена JavaScript кода. Потом захотелось повесить этот код на елементы меню. Поколдовав немного и подменив функцию окна, удалось вклиниться в главное меню Npp. Возможность работать с меню расширила область применения нового плагина (смотри ниже). С появлением меню захотелось сделать его контекстно зависимым. Чтобы например при переключении с файла на файл [де]активировать определенные елементы меню. Так появилась возможность навешивать обработчики событий.

    Подготавливая примеры работы с Plugin'ом я заложил основы для чтения и сохранения настроек.

    Использование


    Ох и надоел я тебе со своими рассказами наверное! Переходим к практике.

    В глобальной области видимости из JavaScript доступен обьект Editor. Доступ к его свойствам и методам возможен так же и без указания его имени.
    /* Properties of Editor */
    /* read only */
    firstView; // a View object
    currentView;// a View object
    secondView;// a View object
    clipBoard;
    langs; // Array of language names
    pluginConfigDir;
    nppDir;
    
    /* read write, bool */
    tabBarHidden;
    toolBarHidden;
    menuHidden;
    statusBarHidden;
    
    /* Methods */
    alert(/**String*/value);
    saveAll();
    open(/**String*/value);
    addMenu(/**String*/ text); // returns a Menu object
    decodeFrom(/** Number*/ codepage, /**String*/ value);
    encodeTo(/** Number*/ codepage, /**String*/ value);
    runMenuCmd(/** Number*/ cmd); // Runs a standart Menu command (see MenuCmds.js)
    setListener(/** Object */ cfg); // see GlobalListener in start.js
    addSystemHotKey(/** Object */ cfg); // adds system hotkey (see example in run.js)
    

    Для работы с текстовыми редакторами Editor предоставляет свойства [firs|current|second]View.
    /* Properties of View */
    /* read write*/
    text;
    file; // number of current file
    selection; // currently selected text
    codepage; // Number of current codepage
    lang; // Number of current language (see Editor.langs)
    line; // Number of current line of text
    pos; // Cursor position
    column; // Cursor position from line begin
    anchor; // Helps to set a selection. Selection is text in interval [anchor, pos]
    
    /* read only */
    files; // Array of strings
    

    Чтобы добавить в главное меню необходимо вызвать Editor.addMenu(«Your Sub menu»). Прямое добавление в главное меню елементов не
    предусмотренно.
    /* Properties of Menu */
    /* read write */
    text;
    checked;
    disabled;
    /* Methods */
    addMenu(/*String*/ text); // adds and returns next submenu
    addMenuItem(/*Object*/cfg); // adds and returns menu item
    
    /* Properties of MenuItem */
    /* read write */
    text;
    checked;
    disabled;
    /* Methods */
    remove();
    
    

    Для затравки я решил привести только небольшой пример (всего на 749байт):
    var xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
    if (xmlHttp){
      // Создаю Меню
      var habrMenu = Editor.addMenu("Хабрахабр");
      xmlHttp.open('GET', 'http://habrahabr.ru/rss/1c9d5ed4f0953ded81510256ed34c9be/', true);
      xmlHttp.onreadystatechange = function () {
        if (xmlHttp.readyState == 4 && xmlHttp.responseXML) {
          var titles = xmlHttp.responseXML.selectNodes("/rss/channel/item/title");
          for(var i=0, c=titles.length; i<c; i++){
            // Создаю для каждой статьи в RSS свой пункт меню
            habrMenu.addItem({
              text: titles[i].text, // название пункта
              link: titles[i].selectSingleNode("../link").text, // сохраняю тут ссылку на статью
              cmd:function(){ // функция вызваемая по нажатию на пункт меню
                var shell = new ActiveXObject("WScript.Shell");
                if (shell && this.link){
                  shell.run(this.link); // Открываю статью в Браузере
                }
            }});
          }
        }
      };
      xmlHttp.send(null);
    }
    
    

    Пример показывает возможности Plugin'а, а так же работу с XML и Shell используя ActiveX.
    www.softwarecanoe.de/pic/nppscripting.habr.png

    Дальнейшие возможности смотри в прилагаемых скриптах из папки includes.
    • run.js — добавляет меню для выполнения JavaScript,
    • clearcase.js — добавляет меню для работы с ClearCase,
    • decode.js — добавляет меню для декодирования текста (практично в не русской Windows),
    • gTranslate.js — добавляет меню для перевода текста с помощью Google Translate,
    • test.menu.js — добавляет меню с примерами и тестами,
    • dialog.js — позволяет, используя Internet Explorer, создавать диалоговые окна,
    • Zen Coding.js — Zen Coding от chikuyonok.

    Пара ссылочек:
    Страница проекта на Google Code,
    Microsoft Windows Scripting

    Happy Scripting!

    UPD: Благодаря стараниям chikuyonok была обнаружена ошибочка, а так же адаптирован Zen Coding для Notepad++!!!
    Ошибка уже исправлена.

    UPD 2: Благодаря стараниям t0H была обнаружена ещё одна ошибочка. В скрытое главное меню не добавлялись новые подменю.
    Ошибка уже исправлена.

    UPD 3: Новая версия и API к ней. Пришлось переименовать plug-in из-за того что уже существовал с таким же именем для программирования на LUA. Так что не забудьте удалить предыдущую версию plug-in'a (NppScripting.dll и NppScripting папку).
    Поделиться публикацией
    AdBlock похитил этот баннер, но баннеры не зубы — отрастут

    Подробнее
    Реклама
    Комментарии 59
    • +1
      Я рад, что для моего любимого EmEditor'a не нужно изобретать ничего подобного — он из коробки поддерживает макросы на Javascript/VBscript (более того, поддерживается запись таких макросов). Больше я не видел текстовых редакторов (кроме офиса со своим VBA) с подобным функционалом. Думаю за ваши старания поклонники Notepad++ тоже скажут вам спасибо.
      • 0
        До вашего коментария не слышал о EmEditor'a :-). Посмотрел, действительно мощьно, правда за деньги и ещё нет поддержики для ClearCase ;-)
      • 0
        А у этого плагина есть возможность заменить фрагмент текста в редакторе? Например, заменить выделенный текст на что-нибудь другое?
        • +1
          это была та самая первая идея.
          // заменим в выделении все пробелы на плюсики
          currentView.selection = currentView.selection.replace(/\s/,'+');


          * This source code was highlighted with Source Code Highlighter.
        • +2
          мне почему то казалось что подобная статья получить больший ажиотаж ;) я как яркий поклонник Notepad++ искренне благодарен вам за проделанную роботу =) единственное, хотелось бы пожелать дальнейшего развития плагина!..
          p.s. очень хочется возможности обработки открытия \ закрытия файла…
          • 0
            Прощу прощения, недосмотрел) Оказывается, прямо сейчас уже можно вешать обработчики. Ещё раз спасибо…
            • 0
              Вы правы, это ожиотаж. Я вообще-то называю это «зараженный человек». Если я от чего-то в восторге, я готов бежать и со всеми делиться. Такое поведение наверное неправильно, тк не все это понимают :-)
            • 0
              Полезная штука. Всё думаю вернуться к notepad++ от textmate. Textmate хвалят-хвалят, а много чего не хватает…
              • +2
                Я сейчас делаю один плагин для Notepad++ на основе вашего, столкнулся с такой проблемой: WSH наотрез отказывается импортирвать JS-файлы, размер которых больше 20 КБ (примерно). При этом программа падает, ссылаясь на другой плагин.

                В качестве решения своей проблемы я вставляю кода плагина прямиком в start.js, что, конечно, не очень хорошо. Может, есть вариант вместо start.js использовать .wsf файл, чтобы можно было подключать файлы более «нативным» способом?
                • 0
                  И ещё вдогонку вопрос: как вызвать диалоговое окно с полем для ввода? Стандартный prompt() не работает.
                  • 0
                    Вы правы, функции нет! Я хотел сразу мощьный инструмент для построения диалогов предоставить. Посмотрите пример «Show Dialog» в меню «Tests» (реализован в tests.menu.js). Используется ИЕ, а это значит что вы можете доволно таки сложные диалоги строить, как для ввода данных так и для управления редактором. Если предполагается частое использование такого диалога, то совет создавать его один раз и по закрытию скрывать, экономите инициализацию ИЕ.
                    Скажу сразу, сам я еще ничего толкового, кроме примера, таким способом не сделал. Уверен prompt() с эмулировать можно :-)
                  • 0
                    хммм!
                    Сохраните ваш плагин в UTF-8!
                    WSF это уже программа от MS, которая использует то же Windows scripting. Про такой же подход для подключения новых скриптов я тоже думал, но это уже другая история.
                    • +1
                      Не помогает. Вот такую ошибку вижу:


                      Причём если я беру свой плагин и сокращаю количество кода в нём, скажем, до 15 КБ, то всё работает (верее, ничего не падает).
                      • 0
                        Хочется надеяться, что ошибку я исправил не наделав новых. Проблема была в том что я освобождал память которую не выделял :-). Zen Coding я выделил в новый файл и добавил в обновленный архив, если вы не против.
                        • 0
                          Внезапно тоже выскочила эта ошибка. Оказывается касперский что-то похерил. Исправил перерегистрацией библиотек — forum.oszone.net/post-1482725.html
                    • +4
                      Вот, собственно, и результат: Zen Coding for Notepad++. Могу сказать, что вы осчастливили многих пользователей этого редактора :)

                      Вы не против того, что я ваш плагин поставляю вместе со своим? Там в readme.txt ваше авторство указано + я удалил все тестовые скрипты.
                      • +1
                        Конечно же я не против! Я рад что плагин находит применение, не смотря на присутствие ошибок. Я предалагаю «Zen Coding for Notepad++» включить в стандартный набор скриптов!
                        • 0
                          Очень оперативно! Спасибо за проделанную работу.
                          • 0
                            Спасибо!
                            Очень приятно использовать!
                            По сравнению с E — просто летает)
                          • 0
                            Спасибо!
                            • 0
                              Спасибо, что реализовали то, что я в свое время не смогла сделать.
                              • +1
                                Спасибо большое действительно удобно…
                                только есть небольшой баг (
                                если меню скрыто и показывается только по нажатию Alt, то новые пункты не добавляются((
                                я из за этого уже два раза обновил программу и кучу всего перепробовал(((
                                • +1
                                  Cпасибо за найденую ошибку. Не продумал такой пример использования.
                                  Уже поправил, в обновленном архиве лежит новая версия Dll.
                                  • 0
                                    Возможно не нашел «обновленного» архива, но у меня все равно работает только так:

                                    var mh = Editor.menuHidden;
                                    Editor.menuHidden = 0;

                                    var testMenu = Editor.addMenu(«Tests»);

                                    Editor.menuHidden = mh;

                                    NPP 5.6.8 UNICODE
                                    Nppscripting.dll 0.1.1.0

                                    Может исходники на google code? Ошибки сами собой находиться будут (не знаю, как выразить смущение)

                                    P.S. Спасибо за плагин.
                                    • 0
                                      Вы немного не туда написали)
                                      а вообще архив действительно обновлен уже…
                                      • 0
                                        По ссылке в топике уже Nppscripting.dll 0.1.2.0.
                                        Я использовал что то подобное, но только на CPP, чтобы получить хендл меню от нпп. Иначе к сожалению никак.
                                  • 0
                                    У меня при нажатии CTRL+E выскакивает ENQ.
                                    • 0
                                      Скорее всего CTRL+E было зарезервировано другим приложением. Попробуйте дургую комбинацию.
                                      • 0
                                        Как изменить комбинацию? Например, хочется ctrl+пробел
                                        • 0
                                          Будет! Но только это все глобально, так что перестанет работать в других приложениях и будет вызывать ваш обработчик в Нпп даже если он не активен!
                                          • 0
                                            Эм… Т.е. эта возомжность будет в скором?
                                            • 0
                                              Давайте попорядку! Опишите что вы и как делаете!

                                              Где вы это обнаружили: сами пишете или используете сторонний яваскрипт?
                                              Какую версию Nppscriptingю.dll вы используете?
                                              Что вы хотите добиться?
                                  • 0
                                    По порядку:
                                    1. есть чистый notepad++ последней версии 5.6.8
                                    2. Ставлю Zen.Coding-Notepad++.v0.6.zip
                                    3. Версия Nppscripting.dll
                                    clip2net.com/clip/m5759/1270197580-clip-7kb.png
                                    4. открываю notepad++, ввеожу «div», нажимаю ctrl+e получаю символ ENQ (как на скриншоте). Если же выбрать пункт меню «Expand Abbreviation», то все разворачивается
                                    • 0
                                      А какая раскладка по умолчанию? Попробуйте английскую поставить по умолчанию и перезапустить Npp! Я думаю заработает :-) Решение проблемы я думаю вы уже понимаете.

                                      1. Если вы используете оригинал Zen Coding то открываете start.js
                                      2. Меняете комбинации в самом внизу файла на другие (русские буковки)
                                      3. Перезапускаете Нпп.

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

                                      А еще я советую вам скачать плагин по ссылке в этой статье. Так как были устранены некоторые ошибки, а Zen Coding выделен в отдельный файл.
                                      • 0
                                        А можно ссылку на issue, где описывается проблема глобальных hotkey'ев? Спасибо
                                        • 0
                                          Я так понимаю, ребята более важной работой завалены. Поэтому каждый интегрирует сам.
                                          • 0
                                            Подозреваю, что из тикета просто не понятен смысл проблемы, из-за этого он наверное и не в приоритете.
                                            • 0
                                              Вы правы.

                                              Они тоже могли бы переспросить, а так вообще никакой реакции. Сильно проявлять инициативу я не стал. Тем более, что это не ошибка, а просто расширение возможностей.

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

                                              Так что, кто хочет интегрирует, а терпеливые ждут новую версию плагина!

                                              ;-)
                                    • 0
                                      Если это из-за того, что CTRL+E занято, то поменять можно так:

                                      в файле Zen Coding.js найдите
                                      строку
                                      addMenuItem('Expand Abbreviation', 'expand_abbreviation', 'Ctrl+E');
                                      и замените CTRL+E на любую удобную вам комбинацию (из клавиш ALT,CTRL,SHIFT и одного символа).
                                      Если вы хотите CTRL+пробел, то нужно чуть-больше поменять:
                                      addMenuItem('Expand Abbreviation', 'expand_abbreviation', 'Ctrl+Space');
                                      • 0
                                        Нечаянно отправил ответ, не дописав его.
                                        Выше, в функции function addMenuItem(name, action, keystroke) {
                                        после строки:
                                        for (var i = 0, il = keys.length; i < il; i++) {
                                        var key = keys[i].toLowerCase();
                                        нужно добавить:
                                        if (key=='space') key=' ';

                                        Тогда у вас сработает CTRL+пробел.
                                    • 0
                                      Это же просто пи… ец! Это нереально удобно! Сегодня только узнал про зен кодинг и сразу плагин для нотпада. Теперь-то я с него точно никогда не слезу. Огромное спасибо!
                                      • 0
                                        Это очень удобно! Я вчера узнал про Zen Coding и нашел плагин для npp сразу 0.7-й версии! Только один вопрос меня мучает — как добавить свои снипеты?
                                        Я в качестве шаблонизатора в некоторых проектах использую смарти и хотелось бы некоторые его конструкции добавить.

                                        Добавляю в plugins\NppScripting\includes\Zen Coding.js — 675-й строкой

                                        'foreach': '{ foreach }\r\n\r\n{ /foreach }',

                                        Перезагружаюсь
                                        В результате получаю закрытый тег foreach
                                      • 0
                                        Кажется разобрался, добавляю в zen_settings секцию

                                        Copy Source | Copy HTML«php»: {
                                          «filters»: «tpl,php,html»,
                                          «extends»: «html,css»,
                                          «snippets»: {
                                            «foreach»: "{ foreach }\n\n{ /foreach }\n",
                                            «foreachelse»: "{ foreach }\n\n{ foreachelse }\n\n{ /foreach }\n"
                                          }
                                        },

                                        при этом у меня в настройках стилей для php назначено пользовательское расширение php, все работает!
                                        Еще раз спасибо Автору.
                                        • 0
                                          Что-то у меня Editor.currentView.column возвращает то же, что Editor.currentView.pos. :(
                                          • +1
                                            А не поделитесь примером!?
                                            • +1
                                              Editor.addMenu("Example").addItem({
                                              	text: "Example",
                                              	cmd: function() {
                                              		alert(Editor.currentView.column - Editor.currentView.pos);
                                              	}
                                              });


                                              В любом файле на любой строке при выполнении этой команды выводится 0.
                                              • 0
                                                Буг :(
                                                • 0
                                                  Южный? :) Кстати. открытие исходников не предвидится?
                                                • 0
                                                  Спасибо за подсказку. Ошибка была уже давно исправлена возможно даже я и не заметил ее. Вот с публикацией новой версии я затянул. Дом-работа-семья.

                                                  Версия для желающих выявить ошибки и нестыковки со скриптами написанными для предыдущей версии. Крохи API документации.
                                                • 0
                                                  Notepad++ 5.9.3 Unicode
                                              • 0
                                                Заинтересовал плагин. В процессе написания своего JS плагина под ваше решение столкнулся с некоторыми трудностями:

                                                Поскольку работает мы уже не в браузере, и вместо стандартного браузерного объекта window, у нас объект Editor, то где искать методы типа setInterval, SetTimout?

                                                И вообще интересует каким образом сделан этот плагин, в плане движка, вряд ли в плагине реализован собственный движок, ведь так?
                                                Я спрашиваю это для того что обратиться к его мануалам и посмотреть какое АПИ доступно кроме описанного вами.
                                                • 0
                                                  Снимаю часть своего вопроса: setTimeout нашел в вашем Api.
                                                  Но вот как реализован JS все равно интересно. Я так понимаю что задействован Windows Host Script, но я попытался использовать его встроенные объекты и у меня ничего не вышло.
                                                  Я не слишком силен в этой специфике, основное направление разработки всегда было WEB…
                                                  • 0
                                                    Используется Scripting Engine. Microsoft предлагает VB и JScript реализованные на ее базисе. Доступны только те объекты, которые видны из javascript и те что вы нашли в Api плагина.

                                                    WHS это совершенно отдельное приложение, которое добавляет свои объекты для облегчения работы с Windows из скрипта. Части WHS реализованны ввиде ActiveX и могут быть использованны в ваших скриптах для Npp.
                                                    Как например
                                                    // объект для работы с файловой системой
                                                    var fso = new ActiveXObject(«Scripting.FileSystemObject»);
                                                    или
                                                    // объект для чтения файла с возможностью указания кодировки
                                                    // советую обратить на него внимание
                                                    var stream = new ActiveXObject(«ADODB.Stream»);

                                                    А тут и тут можно глянуть как работать с базой данных.

                                                    Например так можно новую создать БД
                                                    var cat = new ActiveXObject(«ADOX.Catalog»);
                                                    cat.Create(«Provider='Microsoft.Jet.OLEDB.4.0';Data Source='h:\\new1.mdb'»);

                                                    Успехов!
                                                • 0
                                                  Кто-нибудь в курсе, как в NPP настроить всплывающие подсказки по функциям JS, с параметрами функций?
                                                  например, вот так:
                                                  image

                                                  Пробовал настроить плагин Language Help с разными справочниками *.CHM, всплывающих подсказок нет (не путать с автодополнением)… Но для других языков народ как-то ухитряется настроить, для PHP и т.п.

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