{"id":20915686,"url":"https://github.com/massivemadness/editorkit","last_synced_at":"2025-03-14T11:06:46.441Z","repository":{"id":98175666,"uuid":"608535719","full_name":"massivemadness/EditorKit","owner":"massivemadness","description":"🖊 EditorKit is a multi-language code editor library for Android","archived":false,"fork":false,"pushed_at":"2025-02-19T17:56:58.000Z","size":909,"stargazers_count":77,"open_issues_count":1,"forks_count":10,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-04T14:24:48.252Z","etag":null,"topics":["android","android-library","code-completion","code-editor","java","jflex","kotlin","plugins","syntax-highlighting","text-editor"],"latest_commit_sha":null,"homepage":"https://play.google.com/store/apps/details?id=com.blacksquircle.ui","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/massivemadness.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-03-02T08:10:57.000Z","updated_at":"2025-02-25T11:00:26.000Z","dependencies_parsed_at":"2024-11-19T05:02:52.149Z","dependency_job_id":null,"html_url":"https://github.com/massivemadness/EditorKit","commit_stats":null,"previous_names":[],"tags_count":18,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/massivemadness%2FEditorKit","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/massivemadness%2FEditorKit/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/massivemadness%2FEditorKit/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/massivemadness%2FEditorKit/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/massivemadness","download_url":"https://codeload.github.com/massivemadness/EditorKit/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243565416,"owners_count":20311704,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["android","android-library","code-completion","code-editor","java","jflex","kotlin","plugins","syntax-highlighting","text-editor"],"created_at":"2024-11-18T16:17:22.710Z","updated_at":"2025-03-14T11:06:46.421Z","avatar_url":"https://github.com/massivemadness.png","language":"Java","readme":"# EditorKit\n\n**EditorKit** is a multi-language code editor library for Android.\n\n![Android CI](https://github.com/massivemadness/Squircle-CE/workflows/Android%20CI/badge.svg) [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)\n\n\u003cimg src=\"https://raw.githubusercontent.com/massivemadness/EditorKit/master/.github/carbon.png\" width=\"700\" /\u003e\n\n---\n\n# Table of Contents\n\n## Code Editor\n\n1. [Gradle Dependency](#gradle-dependency)\n2. [The Basics](#the-basics)\n3. [More Options](#more-options)\n    1. [Configuration](#configuration)\n    2. [Text Scroller](#text-scroller)\n4. [Code Suggestions](#code-suggestions)\n5. [Undo Redo](#undo-redo)\n6. [Navigation](#navigation)\n    1. [Text Navigation](#text-navigation)\n    2. [Find and Replace](#find-and-replace)\n    3. [Shortcuts](#shortcuts)\n7. [Theming](#theming)\n8. [Custom Plugin](#custom-plugin)\n\n## Languages\n\n1. [Gradle Dependency](#gradle-dependency-1)\n2. [Custom Language](#custom-language)\n    1. [LanguageParser](#languageparser)\n    2. [SuggestionProvider](#suggestionprovider)\n    3. [LanguageStyler](#languagestyler)\n\n---\n\n# Code Editor\n\nThe `editorkit` module provides code editor without any support for\nprogramming languages.  \n***If you are upgrading from any older version, please have a look at\nthe [migration guide](MIGRATION-GUIDE.md).***  \nPlease note that this library only supports Kotlin.\n\n[![MavenCentral](https://img.shields.io/maven-central/v/com.blacksquircle.ui/editorkit?label=Download)](https://repo1.maven.org/maven2/com/blacksquircle/ui/editorkit/)\n\n## Gradle Dependency\n\nAdd this to your module's `build.gradle` file:\n\n```gradle\ndependencies {\n  ...\n  implementation 'com.blacksquircle.ui:editorkit:2.9.0'\n}\n```\n\nThe `editorkit` module **does not** provide support for syntax\nhighlighting, you need to add specific language dependency. You can see\nlist of available languages [here](#languages-1).\n\n---\n\n## The Basics\n\n**First,** you need to add `TextProcessor` in your layout:\n\n```xml\n\u003ccom.blacksquircle.ui.editorkit.widget.TextProcessor\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:gravity=\"top|start\"\n    android:id=\"@+id/editor\" /\u003e\n```\n\n**Second,** you need to provide a `Language` object to support syntax\nhighlighting by using following code:\n\n```kotlin\nval editor = findViewById\u003cTextProcessor\u003e(R.id.editor)\n\neditor.language = JavaScriptLanguage() // or any other language you want\n```\n\n**Third**, you need to call `setTextContent` to set the text. **Don't\nuse the default `setText` method.**\n\n```kotlin\neditor.setTextContent(\"your code here\")\n```\n\nAlso you might want to use `setTextContent(PrecomputedTextCompat)` if\nyou're working with large text files.\n\n**Finally**, after you set the text you need to clear undo/redo history\nbecause you don't want to keep the change history of previous file:\n\n```kotlin\nimport com.blacksquircle.ui.editorkit.model.UndoStack\n\neditor.undoStack = UndoStack()\neditor.redoStack = UndoStack()\n```\n\nNow you can begin using the code editor.\n\n---\n\n## More Options\n\n### Configuration\n\nYou can change the default code editor behavior by using Plugin DSL as\nshown below:\n\n```kotlin\nval pluginSupplier = PluginSupplier.create {\n    pinchZoom { // whether the zoom gesture enabled\n        minTextSize = 10f\n        maxTextSize = 20f\n    }\n    lineNumbers {\n        lineNumbers = true // line numbers visibility\n        highlightCurrentLine = true // whether the current line will be highlighted\n    }\n    highlightDelimiters() // highlight open/closed brackets beside the cursor\n    autoIndentation {\n        autoIndentLines = true // whether the auto indentation enabled\n        autoCloseBrackets = true // automatically close open parenthesis/bracket/brace\n        autoCloseQuotes = true // automatically close single/double quote when typing\n    }\n}\neditor.plugins(pluginSupplier)\n```\n\nTo enable/disable plugins in runtime, surround necessary methods with\n`if (enabled) { ... }` operator:\n\n```kotlin\nval pluginSupplier = PluginSupplier.create {\n    if (preferences.isLineNumbersEnabled) {\n        lineNumbers()\n    }\n    if (preferences.isPinchZoomEnabled) {\n        pinchZoom()\n    }\n    // ...\n}\neditor.plugins(pluginSupplier)\n```\n\n**Remember:** everytime you call `editor.plugins(pluginSupplier)` it\ncompares current plugin list with the new one, and then detaches plugins\nthat doesn't exists in the `PluginSupplier`.\n\n### Text Scroller\n\nTo attach the text scroller you need to add `TextScroller` in layout:\n\n```xml\n\u003ccom.blacksquircle.ui.editorkit.widget.TextScroller\n    android:layout_width=\"30dp\"\n    android:layout_height=\"match_parent\"\n    android:id=\"@+id/scroller\"\n    app:thumbNormal=\"@drawable/fastscroll_normal\"\n    app:thumbDragging=\"@drawable/fastscroll_pressed\"\n    app:thumbTint=\"@color/blue\" /\u003e\n```\n\nNow you need to pass a reference to a view inside `attachTo` method:\n\n```kotlin\nval editor = findViewById\u003cTextProcessor\u003e(R.id.editor)\nval scroller = findViewById\u003cTextScroller\u003e(R.id.scroller)\n\nscroller.attachTo(editor)\n\n// or using Plugin DSL:\n\nval pluginSupplier = PluginSupplier.create {\n    ...\n    textScroller {\n        scroller = findViewById\u003cTextScroller\u003e(R.id.scroller)\n    }\n}\n```\n\n---\n\n## Code Suggestions\n\nWhen you working with a code editor you want to see the list of code\nsuggestion. *(Note that you have to provide a `Language` object before\nstart using it.)*\n\n**First**, you need to create a layout file that will represent the\nsuggestion item inside dropdown menu:\n\n```xml\n\u003c!-- item_suggestion.xml --\u003e\n\u003cTextView xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"wrap_content\"\n    android:singleLine=\"true\"\n    android:padding=\"6dp\"\n    android:textSize=\"12sp\"\n    android:typeface=\"monospace\"\n    android:id=\"@+id/title\" /\u003e\n```\n\n**Second**, you need to create custom `SuggestionAdapter`:\n\n```kotlin\nclass AutoCompleteAdapter(context: Context) : SuggestionAdapter(context, R.layout.item_suggestion) {\n\n    override fun createViewHolder(parent: ViewGroup): SuggestionViewHolder {\n        val inflater = LayoutInflater.from(parent.context)\n        val view = inflater.inflate(R.layout.item_suggestion, parent, false)\n        return AutoCompleteViewHolder(view)\n    }\n\n    class AutoCompleteViewHolder(itemView: View) : SuggestionViewHolder(itemView) {\n\n        private val title: TextView = itemView.findViewById(R.id.title)\n\n        override fun bind(suggestion: Suggestion?, query: String) {\n            title.text = suggestion?.text\n        }\n    }\n}\n```\n\n**Third**, enable the code completion plugin and set\n`SuggestionAdapter`:\n\n```kotlin\nval pluginSupplier = PluginSupplier.create {\n    ...\n    codeCompletion {\n        suggestionAdapter = AutoCompleteAdapter(this)\n    }\n}\n```\n\n**UPD:** If you having an issues with the popup position (e.g vertical\noffset), this might be solved by explicitly setting\n[android:dropDownAnchor](https://developer.android.com/reference/android/widget/AutoCompleteTextView#attr_android:dropDownAnchor)\nin XML.\n\n---\n\n## Undo Redo\n\nThe `TextProcessor` supports undo/redo operations, but remember that you\n**must** check the ability to undo/redo before calling actual methods:\n\n```kotlin\n// Undo\nif (editor.canUndo()) {\n    editor.undo()\n}\n\n// Redo\nif (editor.canRedo()) {\n    editor.redo()\n}\n```\n\nAlso you may have a use case when you want to update undo/redo buttons\nvisibility or other UI after the text replacements is done, this can be\nachieved by adding `OnUndoRedoChangedListener`:\n\n```kotlin\neditor.onUndoRedoChangedListener = object : OnUndoRedoChangedListener {\n    override fun onUndoRedoChanged() {\n        val canUndo = editor.canUndo()\n        val canRedo = editor.canRedo()\n\n        // ...\n    }\n}\n```\n\n---\n\n## Navigation\n\n### Text Navigation\n\nYou can use these extension methods to navigate in text:\n\n```kotlin\neditor.moveCaretToStartOfLine()\neditor.moveCaretToEndOfLine()\neditor.moveCaretToPrevWord()\neditor.moveCaretToNextWord()\n```\n\n...or use «Go to Line» feature to place the caret at the specific line:\n\n```kotlin\nimport com.blacksquircle.ui.editorkit.exception.LineException\n\ntry {\n    editor.gotoLine(lineNumber)\n} catch (e: LineException) {\n    Toast.makeText(this, \"Line does not exists\", Toast.LENGTH_SHORT).show()\n}\n```\n\n### Find and Replace\n\nThe `TextProcessor` has built-in support for search and replace\noperations, including:\n\n- Search forward or backward\n- Regular Expressions\n- Match Case\n- Words Only\n\nThe class itself contains self-explanatory methods for all your\nsearching needs:\n\n- `find(params)` - Find all possible results in text with provided options.\n- `replaceFindResult(replaceText)` - Finds current match and replaces it with new text.\n- `replaceAllFindResults(replaceText)` - Finds all matches and replaces them with the new text.\n- `findNext()` - Finds the next match and scrolls to it.\n- `findPrevious()` - Finds the previous match and scrolls to it.\n- `clearFindResultSpans()` - Clears all find spans on the screen. Call this method when you're done\n  searching.\n\n```kotlin\nimport com.blacksquircle.ui.editorkit.model.FindParams\n\nval params = FindParams(\n    query = \"function\", // text to find\n    regex = false, // regular expressions\n    matchCase = true, // case sensitive\n    wordsOnly = true // words only\n)\n\neditor.find(params)\n\n// To navigate between results use findNext() and findPrevious()\n```\n\n### Shortcuts\n\nIf you're using bluetooth keyboard you probably want to use keyboard\nshortcuts to write your code faster. To support the keyboard shortcuts\nyou need to enable the shortcuts plugin and set `OnShortcutListener`:\n\n```kotlin\nval pluginSupplier = PluginSupplier.create {\n    ...\n    shortcuts {\n        onShortcutListener = object : OnShortcutListener {\n            override fun onShortcut(shortcut: Shortcut): Boolean {\n                val (ctrl, shift, alt, keyCode) = shortcut\n                return when {\n                    ctrl \u0026\u0026 keyCode == KeyEvent.KEYCODE_DPAD_LEFT -\u003e editor.moveCaretToStartOfLine()\n                    ctrl \u0026\u0026 keyCode == KeyEvent.KEYCODE_DPAD_RIGHT -\u003e editor.moveCaretToEndOfLine()\n                    alt \u0026\u0026 keyCode == KeyEvent.KEYCODE_DPAD_LEFT -\u003e editor.moveCaretToPrevWord()\n                    alt \u0026\u0026 keyCode == KeyEvent.KEYCODE_DPAD_RIGHT -\u003e editor.moveCaretToNextWord()\n                    // ...\n                    else -\u003e false\n                }\n            }\n        }\n    }\n}\n```\n\nThe `onShortcut` method will be invoked only if \u003ckbd\u003ectrl\u003c/kbd\u003e or \u003ckbd\u003ealt\u003c/kbd\u003e is pressed.  \nYou might already noticed that you have to return a `Boolean` value as\nthe result of `onShortcut` method. Return `true` if the listener has\nconsumed the shortcut event, `false` otherwise.\n\n---\n\n## Theming\n\nThe `editorkit` module includes some default themes in the `EditorTheme`\nclass:\n\n```kotlin\neditor.colorScheme = EditorTheme.DARCULA // default\n\n// or you can use one of these:\nEditorTheme.MONOKAI\nEditorTheme.OBSIDIAN\nEditorTheme.LADIES_NIGHT\nEditorTheme.TOMORROW_NIGHT\nEditorTheme.VISUAL_STUDIO\nEditorTheme.INTELLIJ_LIGHT\nEditorTheme.SOLARIZED_LIGHT\nEditorTheme.ECLIPSE\n\n```\n\nYou can also write your own theme by changing the `ColorScheme`\nproperties. The example below shows how you can programmatically load\nthe color scheme:\n\n```kotlin\neditor.colorScheme = ColorScheme(\n    textColor = Color.parseColor(\"#C8C8C8\"),\n    cursorColor = Color.parseColor(\"#BBBBBB\"),\n    backgroundColor = Color.parseColor(\"#232323\"),\n    gutterColor = Color.parseColor(\"#2C2C2C\"),\n    gutterDividerColor = Color.parseColor(\"#555555\"),\n    gutterCurrentLineNumberColor = Color.parseColor(\"#FFFFFF\"),\n    gutterTextColor = Color.parseColor(\"#C6C8C6\"),\n    selectedLineColor = Color.parseColor(\"#141414\"),\n    selectionColor = Color.parseColor(\"#454464\"),\n    suggestionQueryColor = Color.parseColor(\"#4F98F7\"),\n    findResultBackgroundColor = Color.parseColor(\"#1C3D6B\"),\n    delimiterBackgroundColor = Color.parseColor(\"#616161\"),\n    numberColor = Color.parseColor(\"#BACDAB\"),\n    operatorColor = Color.parseColor(\"#DCDCDC\"),\n    keywordColor = Color.parseColor(\"#669BD1\"),\n    typeColor = Color.parseColor(\"#669BD1\"),\n    langConstColor = Color.parseColor(\"#669BD1\"),\n    preprocessorColor = Color.parseColor(\"#C49594\"),\n    variableColor = Color.parseColor(\"#9DDDFF\"),\n    methodColor = Color.parseColor(\"#71C6B1\"),\n    stringColor = Color.parseColor(\"#CE9F89\"),\n    commentColor = Color.parseColor(\"#6BA455\"),\n    tagColor = Color.parseColor(\"#DCDCDC\"),\n    tagNameColor = Color.parseColor(\"#669BD1\"),\n    attrNameColor = Color.parseColor(\"#C8C8C8\"),\n    attrValueColor = Color.parseColor(\"#CE9F89\"),\n    entityRefColor = Color.parseColor(\"#BACDAB\")\n)\n```\n\n## Custom Plugin\n\nSince v2.1.0 the [EditorKit](#editorkit) library supports writing custom\nplugins to extend it's functionality. If you're using the latest version,\nyou might be familiar with `PluginSupplier` and know how to use it's DSL.\nSee [More Options](#more-options) for info.\n\n**First,** you need to create a class which extends the `EditorPlugin`\nand provide it's id in the constructor:\n\n```kotlin\nclass CustomPlugin : EditorPlugin(\"custom-plugin-id\") {\n\n    var publicProperty = true\n\n    override fun onAttached(editText: TextProcessor) {\n        super.onAttached(editText)\n        // TODO enable your feature here\n    }\n\n    override fun onDetached(editText: TextProcessor) {\n        super.onDetached(editText)\n        // TODO disable your feature here\n    }\n}\n```\n\n**Second,** you can override lifecycle methods, for example `onDraw(Canvas)`:\n\n```kotlin\nclass CustomPlugin : EditorPlugin(\"custom-plugin-id\") {\n\n    var publicProperty = true\n\n    private val dividerPaint = Paint().apply {\n        color = Color.GRAY\n    }\n\n    override fun onDraw(canvas: Canvas?) {\n        super.onDraw(canvas)\n        if (publicProperty) {\n            var i = editText.topVisibleLine\n            while (i \u003c= editText.bottomVisibleLine) {\n                val startX = editText.paddingStart + editText.scrollX\n                val startY = editText.paddingTop + editText.layout.getLineBottom(i)\n                val stopX = editText.paddingLeft + editText.layout.width + editText.paddingRight\n                val stopY = editText.paddingTop + editText.layout.getLineBottom(i)\n                canvas?.drawLine( // draw divider for each visible line\n                    startX.toFloat(), startY.toFloat(),\n                    stopX.toFloat(), stopY.toFloat(),\n                    dividerPaint\n                )\n                i++\n            }\n        }\n    }\n}\n```\n\n**Third,** create an extension function to improve code readability when\nadding your plugin to a `PluginSupplier`:\n\n```kotlin\nfun PluginSupplier.lineDividers(block: CustomPlugin.() -\u003e Unit = {}) {\n    plugin(CustomPlugin().apply(block))\n}\n```\n\n**Finally,** you can attach your plugin using DSL:\n\n```kotlin\nval pluginSupplier = PluginSupplier.create {\n    lineDividers {\n        publicProperty = true // whether should draw the dividers\n    }\n    ...\n}\neditor.plugins(pluginSupplier)\n```\n\n---\n\n# Languages\n\nThe language modules provides support for programming languages. This\nincludes syntax highlighting, code suggestions and ~~source code parser~~.\n\n[![MavenCentral](https://img.shields.io/maven-central/v/com.blacksquircle.ui/language-base?label=Download)](https://repo1.maven.org/maven2/com/blacksquircle/ui/language-base/)\n\n## Gradle Dependency\n\nSelect your language and add it's dependency to your module's\n`build.gradle` file:\n\n```gradle\ndependencies {\n  ...\n  implementation 'com.blacksquircle.ui:language-actionscript:2.9.0'\n  implementation 'com.blacksquircle.ui:language-base:2.9.0' // for custom language\n  implementation 'com.blacksquircle.ui:language-c:2.9.0'\n  implementation 'com.blacksquircle.ui:language-cpp:2.9.0'\n  implementation 'com.blacksquircle.ui:language-csharp:2.9.0'\n  implementation 'com.blacksquircle.ui:language-css:2.9.0'\n  implementation 'com.blacksquircle.ui:language-fortran:2.9.0'\n  implementation 'com.blacksquircle.ui:language-go:2.9.0'\n  implementation 'com.blacksquircle.ui:language-groovy:2.9.0'\n  implementation 'com.blacksquircle.ui:language-html:2.9.0'\n  implementation 'com.blacksquircle.ui:language-ini:2.9.0'\n  implementation 'com.blacksquircle.ui:language-java:2.9.0'\n  implementation 'com.blacksquircle.ui:language-javascript:2.9.0'\n  implementation 'com.blacksquircle.ui:language-json:2.9.0'\n  implementation 'com.blacksquircle.ui:language-julia:2.9.0'\n  implementation 'com.blacksquircle.ui:language-kotlin:2.9.0'\n  implementation 'com.blacksquircle.ui:language-latex:2.9.0'\n  implementation 'com.blacksquircle.ui:language-lisp:2.9.0'\n  implementation 'com.blacksquircle.ui:language-lua:2.9.0'\n  implementation 'com.blacksquircle.ui:language-markdown:2.9.0'\n  implementation 'com.blacksquircle.ui:language-php:2.9.0'\n  implementation 'com.blacksquircle.ui:language-plaintext:2.9.0'\n  implementation 'com.blacksquircle.ui:language-python:2.9.0'\n  implementation 'com.blacksquircle.ui:language-ruby:2.9.0'\n  implementation 'com.blacksquircle.ui:language-rust:2.9.0'\n  implementation 'com.blacksquircle.ui:language-shell:2.9.0'\n  implementation 'com.blacksquircle.ui:language-smali:2.9.0'\n  implementation 'com.blacksquircle.ui:language-sql:2.9.0'\n  implementation 'com.blacksquircle.ui:language-toml:2.9.0'\n  implementation 'com.blacksquircle.ui:language-typescript:2.9.0'\n  implementation 'com.blacksquircle.ui:language-visualbasic:2.9.0'\n  implementation 'com.blacksquircle.ui:language-xml:2.9.0'\n  implementation 'com.blacksquircle.ui:language-yaml:2.9.0'\n}\n```\n\n---\n\n## Custom Language\n\n**First,** add this to your module's `build.gradle` file:\n\n```gradle\ndependencies {\n  ...\n  implementation 'com.blacksquircle.ui:language-base:2.9.0'\n}\n```\n\n**Second,** implement the `Language` interface:\n\n```kotlin\nimport com.blacksquircle.ui.language.base.Language\nimport com.blacksquircle.ui.language.base.parser.LanguageParser\nimport com.blacksquircle.ui.language.base.provider.SuggestionProvider\nimport com.blacksquircle.ui.language.base.styler.LanguageStyler\n\nclass CustomLanguage : Language {\n\n    override val languageName = \"custom language\"\n\n    override fun getParser(): LanguageParser {\n        return CustomParser()\n    }\n\n    override fun getProvider(): SuggestionProvider {\n        return CustomProvider()\n    }\n\n    override fun getStyler(): LanguageStyler {\n        return CustomStyler()\n    }\n}\n```\n\nEvery language consist of 3 key components:\n\n1. **LanguageParser** is responsible for analyzing the source code. The\n   code editor does not use this component directly.\n2. **SuggestionProvider** is responsible for collecting the names of\n   functions, fields, and keywords within your file scope. The code\n   editor use this component to display the list of code suggestions.\n3. **LanguageStyler** is responsible for syntax highlighting. The code\n   editor use this component to display syntax highlight spans on the\n   screen.\n\n### LanguageParser\n\n`LanguageParser` is an interface which detects syntax errors so you can\ndisplay them in the `TextProcessor` later.\n\nTo create a custom parser you need to implement `execute` method that\nwill return a `ParseResult`.  \nIf `ParseResult` contains an exception it means that the source code\ncan't compile and contains syntax errors. You can highlight an error\nline by calling `editor.setErrorLine(lineNumber)` method.\n\n**Remember** that you **shouldn't** use this method on the main thread.\n\n```kotlin\nclass CustomParser : LanguageParser {\n\n    override fun execute(structure: TextStructure): ParseResult {\n        // TODO Implement parser\n        val lineNumber = 0\n        val columnNumber = 0\n        val parseException = ParseException(\"describe exception here\", lineNumber, columnNumber)\n        return ParseResult(parseException)\n    }\n}\n```\n\n### SuggestionProvider\n\n`SuggestionProvider` is an interface which provides code suggestions to\ndisplay them in the `TextProcessor`.\n\nThe text scanning is done on a per-line basis. When the user edits code\non a single line, that line is re-scanned by the current\n`SuggestionsProvider` implementation, so you can keep your suggestions\nlist up to date. This is done by calling the `processLine` method. This\nmethod is responsible for parsing a line of text and saving the code\nsuggestions for that line.\n\nAfter calling `setTextContent` the code editor will call `processAllLines`\nto find all possible code suggestions.\n\n```kotlin\nclass CustomProvider : SuggestionProvider {\n\n    // You can use WordsManager\n    // if you don't want to write the language-specific implementation\n    private val wordsManager = WordsManager()\n\n    override fun getAll(): Set\u003cSuggestion\u003e {\n        return wordsManager.getWords()\n    }\n\n    override fun processAllLines(structure: TextStructure) {\n        wordsManager.processAllLines(structure)\n    }\n\n    override fun processLine(lineNumber: Int, text: CharSequence) {\n        wordsManager.processLine(lineNumber, text)\n    }\n\n    override fun deleteLine(lineNumber: Int) {\n        wordsManager.deleteLine(lineNumber)\n    }\n\n    override fun clearLines() {\n        wordsManager.clearLines()\n    }\n}\n```\n\n### LanguageStyler\n\n`LanguageStyler` is an interface which provides syntax highlight spans\nto display them in the `TextProcessor`.\n\nThe `execute` method will be executed on the background thread every\ntime the text changes. You can use regex or lexer to find the keywords\nin text.\n\n**Remember:** the more spans you add, the more time it takes to render\non the main thread.\n\n```kotlin\nclass CustomStyler : LanguageStyler {\n\n    override fun execute(structure: TextStructure): List\u003cSyntaxHighlightResult\u003e {\n        val syntaxHighlightResults = mutableListOf\u003cSyntaxHighlightResult\u003e()\n\n        // TODO Implement syntax highlighting\n\n        return syntaxHighlightResults\n    }\n}\n```\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmassivemadness%2Feditorkit","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmassivemadness%2Feditorkit","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmassivemadness%2Feditorkit/lists"}