Форум Flasher.ru
Ближайшие курсы в Школе RealTime
Список интенсивных курсов: [см.]  
  
Специальные предложения: [см.]  
  
 
Блоги Правила Справка Пользователи Календарь Поиск рулит! Сообщения за день Все разделы прочитаны
 

Вернуться   Форум Flasher.ru > Блоги > e4xu

Всякие разные штуки сомнительной полезности сделанные в свободное от работы время.
Рейтинг: 5.00. Голосов: 2.

JavaScript, все не так плохо

Запись от wvxvw размещена 07.06.2012 в 21:27
Обновил(-а) wvxvw 08.06.2012 в 20:11

Нажмите на изображение для увеличения
Название: jslint-against-the-machines.png
Просмотров: 955
Размер:	9.5 Кб
ID:	269

(На картинке - jslint в шоке от юзерскрипа который обращается к всяким неизвестным ему сущностям типа key, hook, command и т.п.)

Не так давно я стал задумываться, а есть ли жизнь после смерти, на Марсе, и в других местах, где Флеша нету. Одной из промежуточных целей было найти средства вменяемой разработки используя JavaScript. Я как-то слышал хорошие отзывы о Visual Studio, но проверить их не удалось. Попробовал Аптану, но как-то не понравилось, какая-то она "сырая" что ли. Да и вообще, Эклипс...
Вобщем, чего я вас буду вводить в заблуждение, конечно же я искал возможности как бы сделать Эмакс по-удобнее для разработки. И, честно говоря, результат превзошел ожидания! Но давайте сначала и по-порядку.
Эмакс без никаких добавок предлагает javascript-mode. Это умеренно-терпимый мод для редактирования, сами догадываетесь чего. Кроме раскраски и автоматического форматирования в нем практически ничего и нет, ну только немного традиционной навигации от элемента к элементу, к началу функции, концу и т.д. Конечно, для полноценной работы этого не достаточно. Отправился я на поиски, и вот что нашел: http://blog.deadpansincerity.com/201...un-and-profit/ Собственно, тут уже все расписано в деталях, но я добавлю немного от себя. И подведу коротенький итог:

Нужно будет установить Node.js сервер. Этот сервер нужно устанавливать самому (это не сложно, но несколько непривычно, т.как в закромах Debian он не обнаружился). Для справки, что такое Node.js и зачем он нужен: это сервер написаный на С++ который может выполнять JavaScript. А нужен он нам будет для того, чтобы мы могли использовать fly-make (это младший мод в Эмаксе, ответсвенный за подсветку ошибок компиляции, и вообще ошибок синтаксиса), т.как мы будем его использовать в комплекте с jslint'ом - программой написанной Крокфордом (начальником JavaScript отдела в Yahoo!) специально предназначенной для обнаружения ошибок (разного плана, начиная от форматирования и заканчивая ошибками несовпадения типов) в JavaScrip'е. Кроме того, он нам понадобится для того, чтобы общаться с интерпретатором JavaScript'а. (Все ссылки с описанием приведены ниже).

Кроме Node.js и jslint нам понадобится js-comint - это, собственно, и есть интерпретатор, который позволяет нам интерактивно добавлять или изменять уже написанные функции, рассматривать содержание объектов и т.д. К сожалению, такой JavaScript выполняется отдельно от HTML страницы, в которой он будет находиться, что делает тестирование немного затруднительным, но об этом чуть позже.

В статье которую я цитирую говорится еще и о yasnippet (я его не устанавливал, и пока не вижу в нем критической необходимости, кроме того, в комментариях виднеют упоминания о его конфликтах с автоподстановкой, так что я бы пока не рекомендовал).

Автоподстановка, вопреки ожиданиям оказалась вполне сносной. Единственное, надо привыкнуть к тому, что ей нельзя на 100% доверять. Т.е. если автоподстановка не показывает возможное дополнение, это не значит, что его не существует. Но она "обучается по мере работы, ей так же можно скормить все файлы проекта на обработку, и тогда она будет "лучше соображать".
С другой стороны, есть и позитивный момент, т.как в JavaScript'е нет четких границ модулей, такая автоподстановка, основанная только на том, что загружено в данный момент может оказаться на руку, т.как не будет предлагать использовать функции из файлов, которые возможно, к делу отношения не имеют.

Немного дополнительной информации относящейся к тестированию: дя Firefox обнаружился очень занятный плагин, который, кроме того что имитирует горячие клавиши Эмакса, так еще и предоставляет возможность вызова пользовательских скриптов через такой привычный для Эмакса интерфейс: M-x function-name. Кроме того, он умеет общаться с Firebug и еще масса полезных плюшек, которые мне еще предстоит разобрать.
Полезность его заключается еще и в том, что он в интерактивном режиме позволяет нам общаться со скриптами на уровне хрома и на уровне страницы, а так же консолью - что делает отладку гораздо удобнее.

Ниже приводится пошаговое руководство к установке и настройке. Большую часть вы можете так же смело копировать с сайта deadpansincerity, т.как существенных изменений я не делал. Итак:
  • Скачиваем Node.js http://nodejs.org/
  • Распаковываем его куда-нибудь, но все-таки не в Downloads - нам эта папка еще пригодится.
  • Запускаем
    Код:
    $ ./configure
  • Код:
    $ make
  • Код:
    # make install
    (обратите внимание, что инсталлировать нужно из под root'а). Еще такой аспект, у меня во время инсталляции не оказалось установленной SSL библиотеки. Если вы до этого устанавливали Перл, Питон или даже просто Апачи, скорее всего она у вас уже есть, но в случае, если нет:
    Код:
    # apt-get install libssl-dev
    должно хватить.
  • Скачиваем http://npmjs.org/install.sh с http://npmjs.org/ это установщик менеджера пакетов (на манер easy_install в Питоне или Quicklisp в CL).
  • Запускаем его, опять же, с правами администратора.
  • Далее, нам понадобятся следующие утилиты из пакетов npm:
    Код:
    $ git clone https://github.com/davidmiller/lintnode.git
    $ cd lintnode
    $ npm install express connect-form haml underscore
  • Скачиваем js-commint отсюда: http://js-comint-el.sourceforge.net/ и добавляем его на пути просматриваемые Эмаксом. (весь код нужный для подключения к Эмаксу приведен ниже.
  • Автоподстановку можно скачать вот от сюда: http://cx4a.org/software/auto-complete/ она так же здорово облегчает жизнь при написании eLisp скриптов, но собственно, и для Java и для C++ может выступать как подспорье.
    Ее желательно скомпилировать, если собираетесь использовать. http://cx4a.org/software/auto-comple...llation_Script тут описано как это сделать.
  • Код:
    ; this is optional, but nice to have autocomplete library
    (add-to-list 'load-path "~/.emacs.d/")
    (require 'auto-complete-config)
    (add-to-list 'ac-dictionary-directories "~/.emacs.d/ac-dict")
    (ac-config-default)
    (setq-default ac-sources (add-to-list 'ac-sources 'ac-source-dictionary))
    (global-auto-complete-mode t)
    ; Start auto-completion after 2 characters of a word
    (setq ac-auto-start 2)
    ; case sensitivity is important when finding matches
    (setq ac-ignore-case nil)
    
    ; lintnode has the flymake implementation to highlight JavaScript
    ; errors, so we need to load it in order to incorporate it with flymake
    (add-to-list 'load-path "~/projects/lintnode")
    (require 'flymake-jslint)
    ;; Make sure we can find the lintnode executable
    (setq lintnode-location "~/projects/lintnode")
    ;; JSLint can be... opinionated (this is the original comment, I'm
    ;; yet to discover what do eny of these do, but keep them for now)
    (setq lintnode-jslint-excludes (list 'nomen 'undef 'plusplus 'onevar 'white))
    
    (add-hook
     'js-mode-hook
     (lambda ()
       ;; Start the server when we first open a js file and start checking
       (lintnode-hook)
       ;; Scan the file for nested code blocks. Not very useful, but for
       ;; niciety will do
       (imenu-add-menubar-index)
       ;; Activate the folding mode, again, this isn't mandatory, but
       ;; nice to have, read the original post to see what exactly it does
       ;;;; todo: these key bindings might be useful later.
       ;; (global-set-key (kbd "") 'hs-show-block)
       ;; (global-set-key (kbd "") 'hs-show-all)
       ;; (global-set-key (kbd "") 'hs-hide-block)
       ;; (global-set-key (kbd "") 'hs-hide-all)
       (hs-minor-mode t)))
    
    ;; this is the location of js-comint .el files
    ;; we need them for the JavaScript REPL
    (add-to-list 'load-path "~/projects/js-comint/")
    (require 'js-comint)
    
    ;; Use node as our repl
    (setq inferior-js-program-command "node")
    
    ;; various stuff to launch when javascript-mode starts.
    (setq inferior-js-mode-hook
          (lambda ()
            ;; We like nice colors
            (ansi-color-for-comint-mode-on)
            ;; Deal with some prompt nonsense
            (add-to-list
    	 'comint-preoutput-filter-functions
    	 (lambda (output)
    	   ;; ">"
    	   (replace-regexp-in-string
    	    ".*1G\.\.\..*5G" "..."
    	    (replace-regexp-in-string ".*1G.*3G" "* " output))))))
  • Ну и последнее, https://github.com/mooz/keysnail/wiki/ keysnail очень полезный плагин к Firefox, который делает работу в браузере похожей на Эмакс. Инстуркция к установке прямо там же, по ссылке. Ниже пример добавления пользовательской функции, которую можно вызвать через M-x hello-world
    Код:
    function hello_world() {
        alert('Hello world!');
    }
    ext.add("hello-world", hello_world,
            M({ en: "This function shows Hello world alert",
    	    ru: "Эта функция показывает предупреждение Hello world"}));
    Идея такая же как и у Greasemonkey, если не в курсе, то можно почитать тут: http://www.firefoxfacts.com/2009/04/...-greasemonkey/ смысл в том, что вы можете добавлять возможности к браузеру используя JavakScript с той разницей, что можно делать то, что обычно в JavaScript делать нельзя, например, запускать программы на компьютере пользователя, управлять поведением браузера и т.п.

И, совственно, первый практический пример применения. Оно еще немного сыровато, но все-равно приятно. Итак, пример:

Добавляем функцию в .keysnail.js. Эта функция будет зарегистрирована как M-x find-tab. Что делает: показывает окошко с возможностью выбрать закладку на которую нужно мы хотим перейти. Для меня это часто проблема т.как открыто пару десятков закладок и искать в них очень долго - хуже еще и то, что кнопка в Firefox которая показывает все закладки никак не нажимается с клавиатуры. Что мы собственно тут и исправим.

Код AS1/AS2:
function find_tab() {
    var w = window.getBrowser();
    var tabs = w.browsers;
    var s = [];
    for (var i = tabs.length - 1; i >= 0; i--)
    {
	if ('contentTitle' in tabs[i]) s.unshift(tabs[i].contentTitle);
    }
    window.openDialog("file:///home/wvxvw/xul/tabsearch-dialog.xul",
		      "select tab", "select tab", s, w);
}
ext.add("find-tab", find_tab,
        M({ en: "Allows you to chose a browser tab to switch to",
	    ru: "Позволяет перейти на выбранную закладку" }));
Обратите внимание на строчку с tabsearch-dialog.xul - ниже - содержание этого файла, его можно сохранить куда угодно, главное правильно напишите к нему путь. Это файл которых описывает компоненты которые мы будем показывать пользователю (диалоговое окно со списком заполненым именами закладок.

Код:
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin/global.css" type="text/css"?>
<dialog id="whatever" title="Select a tab to open"
        xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
        buttons="accept,cancel"
        buttonlabelcancel="Cancel"
        buttonlabelaccept="Save"
        ondialogaccept="return doOK();"
        ondialogcancel="return doCancel();">
  <dialogheader title="Select tab"/>
  <menulist id="search-box" editable="true"
            oncommand="commandHandler(event)"
            onkeyup="keyUpHandler(event)"/>
  <script>
    var a = window.arguments[0];
    var opener = window.arguments[1];
    var menu = document.getElementById('search-box');

    function doOK()
    {
        opener.selectTabAtIndex(a.indexOf(menu.value));
        return true;
    }

    function doCancel(){ return true; }

    function commandHandler(event)
    {
        doOK();
        window.close();
    }
    
    function keyUpHandler(event)
    {
        var v = menu.value;
        menu.removeAllItems();
        populate(a.filter(function (x, i)
        {
            if (x.toLowerCase() == v.toLowerCase())
		opener.selectTabAtIndex(i);
            return x.toLowerCase().indexOf(v.toLowerCase()) > -1;
        }));
    }
    
    function populate(choices)
    {
        for (var i = choices.length - 1, s; i >= 0; i--)
        {
            s = choices[i];
            menu.appendItem(s, s);
        }
    }
    menu.focus();
    menu.select();
    populate(a);
    // This doesn't seem to work, no idea why.
    menu.open = true;
  </script>
    
</dialog>
Пркатически мало чем отличается от HTML. Перезагружаем .keysnail.js - и готово. Ниже - иллюстрация того, что получилось.

Нажмите на изображение для увеличения
Название: find-tab.png
Просмотров: 401
Размер:	24.6 Кб
ID:	270
Всего комментариев 0

Комментарии

 

 


Часовой пояс GMT +4, время: 00:12.


Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2024, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.