Настройка Sora Editor

от автора

Привет, Хабр

В статье хочу показать как настроить 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/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *