Привет, Хабр
В статье хочу показать как настроить SoraEditor от Resomoe. А конкретно то цветовую схему, язык и простые сниппеты. Так как я не нашел статей по этой теме, а также оффициальная документация в некоторых местах противоречива и не доделана, я решил написать данную статью. Весь код в статье будет на Java.
Про tree sitter и другие прелести с кодом писать не буду, так как об этом хорошо написано в документации.
Подключение…
Для начало добавляем библиотеку в зависимости.
Gradle
dependencies { implementation(platform("io.github.Rosemoe.sora-editor:bom:0.23.4")) implementation("io.github.Rosemoe.sora-editor:editor") implementation("io.github.Rosemoe.sora-editor:language-textmate") }
Maven
<dependencies> <dependency> <groupId>io.github.Rosemoe.sora-editor</groupId> <artifactId>bom</artifactId> <version>0.23.4</version> <type>pom</type> <scope>import</scope> </dependency> <dependency> <groupId>io.github.Rosemoe.sora-editor</groupId> <artifactId>editor</artifactId> </dependency> <dependency> <groupId>io.github.Rosemoe.sora-editor</groupId> <artifactId>language-textmate</artifactId> </dependency> </dependencies>
Нам понадобятся только эти базовые зависимости, где находится сам редактор, и textmate для подсветки синтаксиса.
Далее, обезательно ставим версию JDK 17 или выше, в файле app/build.gradle.
Также, если мы хотим хранить сниппеты в JSON как и остальной кинфиг редактора, нам понадобится библиотека Gson. Она создна для сериализации и десериализации обьектов JSON.
gradle
dependencies { implementation 'com.google.code.gson:gson:2.11.0' }
Maven
<dependency> <groupId>com.google.code.gson</groupId> <artifactId>gson</artifactId> <version>2.11.0</version> </dependency>
Можем синхронизировать проект.
Создание обьекта редактора
Я буду делать все через код, как создать редактор в разметке смотрите в оффициальной документации. Мой редактор будет как корневой элемент активности.
CodeEditor editor; // onCreate(Bundle) editor = new CodeEditor(this); setContentView(editor);
Также, переопределяем метод onDestroy, и в нем вызываем метод release() для освобождения ресурсов.
@Override public void onDestroy() { super.onDestroy(); editor.release(); }
Подсветка синтакиса & язык
Если вам нужна абстрактная подсветка, сниппеты и тема для Java, то можете подключить модуль language-java. Далее использовать его так, если вам нужен другой язык, и больше гибкости, то можете читать статью дальше. Примео использования language-java
editor.setEditorLanguage(new JavaLanguage());
Создаем такое дерево файлов и папок в ассетах:
. └─ textmate ├─ lua │ ├─ lua.tmLanguage.json │ └─ language-configuration.json ├─ langs.json └─ dercula.json // схема
Язык и тему, можно можно выбрать любую, но она должна создана именно для textmate, в формате JSON. Вы также сами можете делать темы и языки в ручную.
Вы можете как вам угодно размещать папки и файлы, главное не забыть поменять пути на новые в файле langs.json.
Пример textmate/langs.json:
{ "languages": [ { "grammar": "textmate/lua/lua.tmLanguage.json", "name": "lua", "scopeName": "source.lua", "languageConfiguration": "textmate/lua/language-configuration.json" } ] }
А, ну и все необходимые ресурсы можете скачать сдесь: VSCode Extensions.
Цветовая схема редактора
Я сразу предоставлю код который будет настраивать схему, так как в документации об этом подробно написано. Предоставлю в качестве метода.
Функция инициализации цветовой схемы
public static void initSchemes(Context context) { FileProviderRegistry.getInstance() .addFileProvider(new AssetsFileResolver(context.getAssets())); var themeRegistry = ThemeRegistry.getInstance(); String name = "darcula"; String themeAssetsPath = "textmate/" + name + ".json"; ThemeModel model = new ThemeModel( IThemeSource.fromInputStream( FileProviderRegistry.getInstance() .tryGetInputStream(themeAssetsPath), themeAssetsPath, null), name); try { themeRegistry.loadTheme(model); } catch (Exception err) { err.printStackTrace(); } GrammarRegistry.getInstance().loadGrammars("textmate/langs.json"); }
Далее нужно установить собственно тему и язык в редактор. Так как там очень мало кода, помещу в 1 фрагмент.
Установка темы и языка
// устанавливаем тему ThemeRegistry .getInstance() .setTheme("Darcula"); // устанавливаем язык String languageScopeName = "source.lua"; try { TextMateLanguage language = new TextMateLanguage(languageScopeName); editor.setEditorLanguage(language); } catch (Exception e) { e.printStackTrace(); }
Сниппеты
Этого в документации вобще нет, так что думаю будет трудновато самому об этом узнать. Сделаем простейшие сниппеты, а далее можно самому разбираться, так как у SoraEditor открытый исодный код на гитхабе.
Для начало создадим файл snippets.json, со следующим содержанием.
[ { "prefix": "var", "body": [ "local a = 0" ], "description": "create variable", "length": 3 } // Другие сниппеты ]
На самом деле вы можете сделать любую свою структуру сниппета, так, как вам будет удобно. Я буду ориентировать именно на такую структуру.
Далее создадим наследник класса TextMateLanguage, я назову его TML, пример кода:
public class TML extends TextMateLanguage { private String scope; public TextMateLanguage(String scopeName) { super( GrammarRegistry.getInstance().findGrammar(scopeName), GrammarRegistry.getInstance().findLanguageConfiguration(scopeName), GrammarRegistry.getInstance(), ThemeRegistry.getInstance(), true); scope = scopeName; } }
Что за что отвечает можете посмотреть в исходниках в модуле textmate.
Переопределяем метод requireAutoComplete:
public class TML extends TextMateLanguage { // ... конструктор @Override public void requireAutoComplete( ContentReference content, CharPosition position, CompletionPublisher publisher, Bundle extraArguments) { super.requireAutoComplete(content, position, publisher, extraArguments); for (SnippetReader.Snippet s : SnippetReader.read(context, "lua")) { publisher.addItem( new SimpleCompletionItem( s.prefix, s.description, s.length, s.text) ); } CompletionHelper.computePrefix(content, position, MyCharacter::isJavaIdentifierPart); } }
SnippetReader — кастомный класс для чтения сниппетов из ассетов. Немного позже разберем этот класс.
Будем делать сниппеты с помощью обьекта pulisher и класса SimpleComplectionItem, у него довольно много конструкторов, мы будем использовать такой:
SimpleCompletionItem( label, desc, prefixLength, textToInsert)
Остальное можете просто скопировать.
Класс SnippetReader
Вобщем не вижу смысла тянуть, сразу дам код. Если что, для чтения ассетов использую свою библиотеку под названием Assets++.
public class SnippetReader { public static Snippet[] read(Context c, String langName) { String json = Assets.from(c).asset( String.format( "textmate/%s/snippets.json", langName)) .readAsset(); Type snippetsListType = new TypeToken<Snippet[]>() {}.getType(); Snippet[] snippets = new Gson().fromJson(json, snippetsListType); for(Snippet s : snippets) { s.text = String.join("\n", s.body); } return snippets; } public static class Snippet { @SerializedName("prefix") public String prefix; @SerializedName("body") public String body; @SerializedName("description") public String description; @SerializedName("length") public int length; public String text; } }
Завершение
По итогу, мы настроили тему для редактора, язык а также простые сниппеты. Вопросы, поправки, предложения пишите ниже.
ссылка на оригинал статьи https://habr.com/ru/articles/863272/
Добавить комментарий