- PVSM.RU - https://www.pvsm.ru -

Как начать писать приложения на ClojureDart

16 апреля зарелизился ClojureDart, а это значит, что для любителей Clojure открылась возможность писать мобильные, веб- и десктоп-приложения на Flutter. Зачем использовать для этого Clojure, как бы очевидно это ни было, выходит за границы фокуса статьи.

На текущий момент инструменты еще не отшлифованы, нет репла(!) и автодополнений для dart-интеропа, но пользоваться можно, и некоторые плюшки кложуры уже показали себя (например, nest [1]-макрос, убирающий проблему вложенности, а вот код side-by-side [2]).

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

И еще, статья [3] будет поддерживаться на гитхабе.

Tools

Ставим Flutter по официальной инструкции [4] и cli [5] для Clojure. Дополнительно не помешает clj-kondo [6], через который сейчас работают ворнинги для макроса apha/widget [7].

Вот как это выглядит:

Как начать писать приложения на ClojureDart - 1

Выбор редактор кода

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

VSCode — быстрый старт

Я не пользователь VSCode, но насколько мне известно, это самый простой способ начать. Устанавливаем Calva, и все заработает само:

Как начать писать приложения на ClojureDart - 2

Не помешает поставить Flutter extenstion, подробнее тут [8].

Плюсы:

  • скорость и простота использования;

  • уникальный плагин Joyride [9], позволяющий писать настройки редактора с реплом на Clojure.

Intellij Idea — ожидаем поддержку

Результат, на который можно рассчитывать сейчас:

Как начать писать приложения на ClojureDart - 3

Есть автодополенения для Clojure (пример с reduce- выше), но интеропа с дартом нет и отключить эти ворнинги нельзя.

Плюсы:

  • почти ничего не нужно настраивать и чинить;

  • поддержка придет в ближайшем будущем, и все заработает без вашего участия.

Минусы:

  • экстремально медленно открывается проект (до минуты на hello-world на моем air-е, с вимом я жду 125 мс);

  • нет возможности настроить подсветку и автодополнения (только выключить);

Чтобы настроить поддержку *.cljd, необходимо указать расширение для clojure:
preferences -> editor -> filetypes -> clojure file -> file patterns -> + -> *.cljd
Поддержка Flutter настраивается плагинами для Дарта и Флаттера, подробнее тут [10].
Поддержка ворнингов clj-kondo работает с плагином clojure-extras [11].

Vim — кастомизация

Тот же пример с reduce-

Как начать писать приложения на ClojureDart - 4

Плюсы:

  • скорость открытия, возможность открывать с десяток(сотню) проектов одновременно за миллисекунды;

  • расширенная кастомизация;

  • репл сам интегрируется в работу с выходом репла для ClojureDart;

  • возможность писать конфиги на лиспе (см. ниже).

Минусы:

  • нужно научиться пользоваться вимом;

  • нужно потратить время и настроить все самому;

  • иногда нужно заниматься починкой после обновления плагинов и самого вима.

Есть несколько опций, как завести вим для ClojureDart.

Nvim с lsp

Ставим плагин [12] и 2 сервера — для Clojure [13] и Flutter [14] (полезные для флаттер-разработки команды [15] + базовый функционал для работы с дартом).
Прописываем настройку для распознавания *.cljd как Clojure:

au! BufRead,BufNewFile *.cljd setfiletype clojure

Я сейчас пользуюсь такой конфигурацией, и за исключением интеропа с дартом в ней есть практически все (рефакторинг, goto definition, find usages, автодополнения, документация, чистка неймспесов) .

Мой конфиг [16] описан на Fennel. Подробный разбор за рамками статьи, но если все же захочется использовать лисп, то я бы посоветовал начать с плагина aniseed [17] и дотфайлов [18] автора. В качестве начального конфига так же можно взять этот проект [19], либо готовую сборку nyoom [20].

Vim/nvim с плагином VimIced

Нужно настроить VimIced по инструкции [21] и подключить clj-kondo в качестве линтера (по этой [22] инструкции). Пока еще нет ClojureDart-репла, большей частью функционала будет пользоваться нельзя.

Fireplace

Не проверял этот плагин [23], но наверняка будет работать сопоставимо с VimIced, если где-то в виме прописать, что cljd -> это кложур.

au! BufRead,BufNewFile *.cljd setfiletype clojure

Emacs

Разработчики ClojureDart пользуются Emacs, в Clojure-mode [24] уже добавили распознавание *.cljd. На мой взгляд, плюсы и минусы сопоставимы с вимом, а остальное — на любителя.

Workflow

Рекомендую начать с hello-world [25], чтобы убедиться, что все работает.

В процессе работы удобно держать открытыми (под рукой) 3 окна:

  1. Любой файл на дарте (можно создать дарт-файл в директории lib/), чтобы тут же экспериментировать, смотреть сигнатуры, методы, поля и пр.

  2. Терминал, чтобы видеть логи и взаимодействовать с проектом.

  3. Эмулятор (по моему опыту андроид-эмулятор стабильнее и быстрее веб-версии). Самый простой способ настроить его — установить AndroidStudio, и воспользоваться Tools->DeviceManagement.

После запуска "watcher"-а:
сlj -M -m cljd.build flutter
Входим в петлю интерактивной разработки: пишем код, сохраняем файл, видим результат, снова пишем код...

Если нужен hot-reload, сохраняем файл.
Если нужен hot-restart, жмем Enter в терминале.
Если все перестает работать, удаляем папку .clojuredart/ и перезапускаем "watcher".

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

Как и в обычным Flutter-проекте, добавляем библиотеки в pubspec.yaml файл. Импортируем строкой, как и в *.dart файлах в формате, как в обычном Clojure:

(:require
    [clojure.string :refer [join]]
    ["package:graphql/client.dart" :as g])

Единственный способ использовать свои dart-классы — выложить их отдельный проектом и добавить в pubspec.yaml. Возможно, в будущем добавят поддержку.

Подход в построении дерева виджетов отличается от Flutter на Dart

Практически всегда имеет смысл создать функцию (как в примерах [26]:2 от авторов), а не объявить класс с deftype (как я сделал тут [27]:4). Для создания же StatefulWidget удобнее всего использовать макрос alpha/widget [7].

ClojureDart отличается от Clojure

В первую очередь, рекомендую прочесть доку [28] от авторов.

Другое отличие, с которым вы обязательно столкнетесь, это отсутствие библиотек, которые бы переводили данные в старые-добрые кложуровские PersistentHashMap. В примере [29](3) с GraphQL я написал функцию для перевода дартовой Map в кложуровую PersistentHashMap.

Куда идти с вопросами?

Сообщество сидит в слеке clojurians [30], канал #clojuredart. Большую часть вопросов уже задали, и можно "загуглить" их в чате. Авторы активно помогают, отвечают на все вопросы. Можно даже залить проект на гитхаб, и попросить совета/помощи в чате. Кто-то обязательно посмотрит.

Полезные ресурсы

  1. Официальная документация [31] по ClojureDart.

  2. Примеры кода [26] от авторов.

  3. Пример приложения [32] c GraphQL и TEA-архитектурой.

  4. Пример [27] написания кастомных виджетов с deftype.

  5. Сообщество в Слеке — clojurians [30], канал #clojuredart

Автор: Артур Думчев

Источник [33]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/dart/374732

Ссылки в тексте:

[1] nest: https://github.com/Tensegritics/ClojureDart/blob/main/doc/flutter-helpers.md#nest-macro

[2] side-by-side: https://twitter.com/cgrand/status/1517652416396730369?t=T2md7PwYw8kfbulzAlVhUQ&s=09

[3] статья: https://github.com/Liverm0r/HowToClojureDart/blob/main/README.md

[4] инструкции: https://docs.flutter.dev/get-started/install

[5] cli: https://clojure.org/guides/deps_and_cli

[6] clj-kondo: https://github.com/clj-kondo/clj-kondo

[7] apha/widget: https://github.com/Tensegritics/ClojureDart/blob/main/doc/flutter-helpers.md#widget-macro

[8] тут: https://docs.flutter.dev/development/tools/vs-code

[9] Joyride: https://marketplace.visualstudio.com/items?itemName=betterthantomorrow.joyride

[10] тут: https://docs.flutter.dev/development/tools/android-studio

[11] clojure-extras: https://plugins.jetbrains.com/plugin/18108-clojure-extras

[12] плагин: https://github.com/neovim/nvim-lspconfig

[13] Clojure: https://github.com/neovim/nvim-lspconfig/blob/master/doc/server_configurations.md#clojure_lsp

[14] Flutter: https://github.com/akinsho/flutter-tools.nvim

[15] команды: https://github.com/akinsho/flutter-tools.nvim#usage

[16] конфиг: https://github.com/Liverm0r/dotfiles/blob/master/.config/nvim/fnl/plugin/lspconfig.fnl

[17] aniseed: https://github.com/Olical/aniseed

[18] дотфайлов: https://github.com/Olical/dotfiles/tree/main/stowed/.config/nvim

[19] проект: https://github.com/rafaeldelboni/nvim-fennel-lsp-conjure-as-clojure-ide

[20] nyoom: https://github.com/shaunsingh/nyoom.nvim

[21] инструкции: https://liquidz.github.io/vim-iced/

[22] этой: https://github.com/clj-kondo/clj-kondo/blob/master/doc/editor-integration.md#ale

[23] этот плагин: https://github.com/tpope/vim-fireplace

[24] Clojure-mode: https://github.com/clojure-emacs/clojure-mode/blob/master/clojure-mode.el

[25] hello-world: https://github.com/Tensegritics/ClojureDart/blob/main/doc/flutter-quick-start.md

[26] примерах: https://github.com/Tensegritics/ClojureDart/tree/main/samples

[27] тут: https://github.com/Liverm0r/minataurus/blob/custom-widget/src/minataurus/fab.cljd

[28] доку: https://github.com/Tensegritics/ClojureDart/blob/main/doc/differences.md

[29] примере: https://github.com/Liverm0r/ClojureDartTeaExample/blob/main/src/tea/api.cljd

[30] clojurians: https://clojurians.slack.com

[31] документация: https://github.com/Tensegritics/ClojureDart/tree/main/doc

[32] Пример приложения: https://github.com/Liverm0r/ClojureDartTeaExample

[33] Источник: https://habr.com/ru/post/664026/?utm_source=habrahabr&utm_medium=rss&utm_campaign=664026