воскресенье, 4 апреля 2010 г.

Работаем с F# в Emacs


Сегодня мы поговорим о том, как использовать замечательный редактор Emacs для разработки на языке F# от одной небезызвестной корпорации.

Не секрет, что синтаксис языка программирования F# был чуть менее, чем целиком позаимстован с синтаксиса OCaml, поэтому, чтобы на нем было удобно программировать в Emacs - достаточно адаптировать режим для OCaml, добавив работу с отступами, потому что в F# как и в Python отступы имеют значение, и с интерпретатором fsi. К счастью работа по адаптации уже проведена: Laurent Le Brun создал fsharp-mode, который хостится на SourceForge. Проект сейчас находится в стадии alpha, однако умеет следующее:

1. Подсветку синтаксиса.
2. Работу с отступами: автоматическую расстановку отступов, сдвиги блоков кода влево-вправо и т.д.
3. Работу с интерпретатором F# - fsi.exe. Можно отправлять произвольные блоки кода на интерпретацию нажатием комбинации клавиш и видеть результат интерпретации в отдельном интерактивном буфере.

Рассмотрим подключение режима, его настройку и использование подробнее.


Прежде всего следует скачать архив отсюда и распаковать в каталог, содержащий ваши .el-файлы, например в ~/.emacs.d/modes/fsharp. Архив включает в себя пять файлов: README - краткая справка с контактами автора, информацией по установке, настройке и имеющимся комбинациям клавиш; fsharp-font.el - файл с настройками подсветки синтаксиса; fsharp-indent.el - файл, в котором содержится код, обеспечивающий работу с отступами; fsharp.el - основной файл режима и inf-fsharp.el - файл, содержащий код работы с интерпретатором F#.

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

  1. (load-file "/home/pavel/.emacs.d/modes/fsharp/fsharp-font.el")

  2. (load-file "/home/pavel/.emacs.d/modes/fsharp/fsharp-indent.el")

  3. (load-file "/home/pavel/.emacs.d/modes/fsharp/fsharp.el")

  4. (load-file "/home/pavel/.emacs.d/modes/fsharp/inf-fsharp.el")



Стоит обратить внимание, что важен порядок загрузки файлов.

Теперь можно перейти непосредственно к настройке. Я создал файл ~/.emacs.d/rc/emacs-rc-fsharp.el, содержащий следующий код:

  1. (setq auto-mode-alist (cons '("\\.fs[iylx]?$" . fsharp-mode) auto-mode-alist))

  2. (autoload 'fsharp-mode "fsharp" "Major mode for editing F# code." t)

  3. (autoload 'run-fsharp "inferior-fsharp" "Run an inferior F# process." t)

  4.  

  5. (setq inferior-fsharp-program "mono /opt/fsharp/bin/fsi.exe --readline-")

  6. (setq fsharp-compiler "mono /opt/fsharp/bin/fsc.exe")



Рассмотрим его подробнее. В первой строчке мы указываем Emacs'у автоматически переходить в режим fsharp-mode при редактировании файлов с разширением .fs, .fsi, .fsx и т.д.

Вторая и третья строчки служат для автоматической загрузки режимов fsharp-mode и run-fsharp. Последний режим - это режим взаимодействия с интерпретатором F#.

В третьей и четвертой строчке настраиваем пути к интерпретатору (inferior-fsharp-program) и компилятору (fsharp-compiler), соответственно. Т.к. я работаю под Linux, то использую mono в качестве среды, предоставляющей CLR.

Пару слов о запуске интерпретатора F#. Параметр командной строки --readline- служит для того, чтобы выключить использование библиотеки readline интерпретатором. Если не указать данный параметр - интерпретатор не работает с Emacs, т.е. он выведет приглашение командной строки в отдельный буфер, однако считывать вводимые с клавиатуры команды не будет. При использовании ключа --readline- интерпретатор будет работать нормально.

Теперь рассмотрим работу в режиме fsharp-mode. Подцветка синтаксиса выглядит следующим образом:



Если после ввода строки нажать Enter, то курсор на новой строке автоматически сдвинется на нужную позицию - на 4 пробела правее, если мы создаем новый блок. Клавиша TAB выполняет две функции: она сдвигает новую строку на 4 пробела вправо, а при повторном нажатии - на 4 пробела влево.

Так как в языке F# отступы имеют значение и каждый блок кода выделяется 4-мя пробелами, то в Emacs необходимо настроить замену табуляций на пробелы. В принципе, при наличии автоматической расстановки отступов, клавиша TAB используется не часто, но все равно будет удобнее нажимать ее вместо того, чтобы 4 раза нажимать пробел. Для автоматической замены табуляции на 4 пробела в настройки Emacs нужно добавить следующие строки:

  1. (setq-default tab-width 4)

  2. (setq-default indent-tabs-mode nil)



Сейчас в режиме fsharp-mode определены и работают следующие комбинации клавиш:

1. C-c C-r (C обозначает Control) - выполнить выделенный регион в интерпретаторе.
2. C-c C-e - выполнить текущий блок кода в интерпретаторе. Текущим называется блок кода, в котором находится курсор.
3. C-M-x (M обозначает Meta, в случае IBM PC - Alt) - выполнить текущий блок кода в интерпретаторе.
4. C-M-h - выделить текущий блок кода в интерпретаторе. Удобная штука - после выделения блок кода можно скопировать, вырезать и т.д.
5. C-c C-s - показать буфер интерпретатора
6. C-c C-c - компилировать файл с помощью fsc.exe
7. С-с С-a - найти и открыть альтернативный файл (.fsi для .fs и наоборот)
8. C-c r - сдвинуть блок кода вправо
9. C-c l - сдвинуть блок кода влево.

Лично мне показались неудобными комбинации клавиш для исполнения блоков кода в интерпретаторе, поэтому я их переопределил. Для этого нужно в файл ~/.emacs.d/rc/emacs-rc-fsharp.el добавить следующий код:

  1. (defun my-fsharp-mode-hook ()

  2.   (local-set-key "\C-x"      'fsharp-eval-region)

  3.   (local-set-key "\C-e"      'fsharp-eval-phrase)

  4.   (local-set-key "\C-c\C-w"  'fsharp-mark-phrase)

  5. )

  6.  

  7. (add-hook 'fsharp-mode-hook 'my-fsharp-mode-hook)



Данный код назначает исполнение выделенного региона на C-x, исполнение текущего блока кода на C-e, выделение текущего блока кода на C-c C-w.

Работа с интерпретатором мало отличается от тех возможностей, которые имеет Visual Studio, главное - привыкнуть к настроенным комбинациям клавиш.



Может быть работа с F# в Emacs не настолько удобна, как в Visual Studio, но, судя по коду, автор режима планирует добавить методы, вычисляющие тип выражения, отображающие справку, реализующие автоподстановку и т.д. Надеюсь, что проект будет развиваться. Тех возможностей, которые есть сейчас вполне достаточно для использования F# в учебных целях. Методы и поля того или иного класса можно смотреть в MSDN, а встроенная автоподставнока и подсказки при изучении языка более вредны, чем полезны.

Понравилось сообщение - подпишитесь на блог или читайте меня в twitter

6 комментариев:

Alex Ott комментирует...

по хорошему, надо написать парсер F# для CEDET, и тогда много функций, типа показа сигнатуры функций и т.п., будет работать из коробки

Unknown комментирует...

Если я правильно понимаю, то основная сложность - сделать для CEDET некий справочник .NET-овских библиотечных функций. Потому что, если ограничиться только функциями, написанными программистом, то толку будет не много.

Michael Kazarian комментирует...

2Alex Ott Если при выхове интерпретатора указан ключ --readline+ то автодополнение происходит прямо в интерпретаторе. То есть, есть смысл передавать из буфера туда и что-то мудрить, что бы вывести данные

Unknown комментирует...

Замечу, что в Emacs (по крайней мере под линуксом) интерпретатор с ключом --readline+ не работает.

Alex Ott комментирует...

2Pavel: ну насколько я понимаю, ничто не мешает написать тулзу, которая бы сгенерировала бы БД функций для semanticdb (примитивный вариант такой тулзы есть для Java). Хотя лучше бы это обсудить с автором CEDET

Michael Kazarian комментирует...

2 Pavel А не обязательно это делать в емакс. Можно запустить отдельный фоновый процесс и общаться уже с ним.

Отправить комментарий

Любой Ваш комментарий важен для меня, однако, помните, что действует предмодерация. Давайте уважать друг друга!