Giter VIP home page Giter VIP logo

compose-code-editor's Introduction

Compose Code Editor (Multiplatform)

Description

Compose Code Editor is a code highlighting / editing library for compose , it does not make use of web view so it renders fast

It also supports kotlin multiplatform and supports Android,JVM & Web at the moment , It will be better if you could get it from github packages since I use that and post latest versions there and Jitpack might not support multiplatform The version 2.0.3 is only for Android , Its 3.0.0 and afterwards for multiplatform

Demo

Screen Recording (9-11-2021 4-29-35 PM)

Setup

You can either get this from github packages or jitpack, Please note that Jitpack is android only.

Multiplatform Dependency

Step 1 : Add the Github Packages Repo

val githubProperties = Properties()
githubProperties.load(FileInputStream(rootProject.file("github.properties")))

allprojects {
    repositories {
        maven("https://maven.pkg.github.com/username/repo") {
            name = "GitHubPackages"
            credentials {
                username = (githubProperties["gpr.usr"] ?: System.getenv("GPR_USER")).toString()
                password = (githubProperties["gpr.key"] ?: System.getenv("GPR_API_KEY")).toString()
            }
        }
    }
}

Step 2 : Create Github Properties File

Create github.properties file in your project at root level and add two properties (make github personal access token)

gpr.usr=yourgithubusername
gpr.key=yourgithubpersonalaccesstoken

Or you could also set "GPR_USER" (your github username) or "GPR_API_KEY" (your github personal access token) as environment variables This would be very easy and you don't need to worry about checking out this file in git.

Step 3 : Add The Dependency

implementation("com.wakaztahir:codeeditor:3.0.5")

Android Only Dependency

Step 1. Make sure you have jitpack repository in your build file

allprojects {
    repositories {
        maven { url 'https://jitpack.io' }
    }
}

Step 2. Add the dependency

dependencies {
    implementation 'com.github.qawaz:compose-code-editor:2.0.3'
}

Usage

// Step 1. Declare Language & Code
val language = CodeLang.Kotlin
val code = """             
    package com.wakaztahir.codeeditor
    
    fun main(){
        println("Hello World");
    }
""".trimIndent()

// Step 2. Create Parser & Theme
val parser = remember { PrettifyParser() } // try getting from LocalPrettifyParser.current
var themeState by remember { mutableStateOf(CodeThemeType.Monokai) }
val theme = remember(themeState) { themeState.theme() }

Using Text Composable

// Step 3. Parse Code For Highlighting
val parsedCode = remember {
    parseCodeAsAnnotatedString(
        parser = parser,
        theme = theme,
        lang = language,
        code = code
    )
}

// Step 4. Display In A Text Composable
Text(parsedCode)

Using TextField Composable

var textFieldValue by remember {
  mutableStateOf(
    TextFieldValue(
      annotatedString = parseCodeAsAnnotatedString(
        parser = parser,
        theme = theme,
        lang = language,
        code = code
      )
    )
  )
}

OutlinedTextField(
  modifier = Modifier.fillMaxSize(),
  value = textFieldValue,
  onValueChange = {
    textFieldValue = it.copy(
      annotatedString = parseCodeAsAnnotatedString(
        parser = parser,
        theme = theme,
        lang = language,
        code = it.text
      )
    )
  }
)

Displaying Line Numbers

To display line numbers in the text field we must use a BasicTextField since it has a parameter for onTextLayout

A basic example can be setup like this , On every text layout a new array is created which contains top offsets of each line in the BasicTextField

val language = CodeLang.Kotlin
val code = """             
    package com.wakaztahir.codeeditor
    
    fun main(){
        println("Hello World");
    }
    """.trimIndent()

val parser = remember { PrettifyParser() }
val themeState by remember { mutableStateOf(CodeThemeType.Default) }
val theme = remember(themeState) { themeState.theme }

fun parse(code: String): AnnotatedString {
    return parseCodeAsAnnotatedString(
        parser = parser,
        theme = theme,
        lang = language,
        code = code
    )
}

var textFieldValue by remember { mutableStateOf(TextFieldValue(parse(code))) }
var lineTops by remember { mutableStateOf(emptyArray<Float>()) }
val density = LocalDensity.current

Row {
    if (lineTops.isNotEmpty()) {
        Box(modifier = Modifier.padding(horizontal = 4.dp)) {
            lineTops.forEachIndexed { index, top ->
                Text(
                    modifier = Modifier.offset(y = with(density) { top.toDp() }),
                    text = index.toString(),
                    color = MaterialTheme.colors.onBackground.copy(.3f)
                )
            }
        }
    }
    BasicTextField(
        modifier = Modifier.fillMaxSize(),
        value = textFieldValue,
        onValueChange = {
            textFieldValue = it.copy(annotatedString = parse(it.text))
        },
        onTextLayout = { result ->
            lineTops = Array(result.lineCount) { result.getLineTop(it) }
        }
    )
}

List of available languages & their extensions

Default ("default-code"), HTML ("default-markup") , C/C++/Objective-C ("c", "cc", "cpp", "cxx", "cyc", "m"), C# ("cs"), Java ("java"),Kotlin ("kt") ,Bash ("bash", "bsh", "csh", "sh"), Python ("cv", "py", "python"), Perl ("perl", "pl", "pm"), Ruby ("rb", "ruby"), JavaScript ("javascript", "js"), CoffeeScript ("coffee"), Rust ("rc", "rs", "rust"), Appollo ("apollo" , "agc", "aea"), Basic ("basic", "cbm"), Clojure ("clj"), Css ("css"), Dart ("dart"), Erlang ("erlang", "erl"), Go ("go"), Haskell ("hs"), Lisp ("cl", "el", "lisp", "lsp", "scm" , "ss", "rkt"), Llvm ("llvm", "ll"), Lua ("lua"), Matlab ("matlab"), ML (OCaml, SML, F#, etc) ("fs", "ml"), Mumps ("mumps"), N ("n", "nemerle"), Pascal ("pascal"), R ("r", "s", "R" , "S", "Splus"), Rd ("Rd", "rd"), Scala ("scala"), SQL ("sql"), Tex ("latex", "tex"), VB ("vb", "vbs"), VHDL ("vhdl", "vhd"), Tcl ("tcl"), Wiki ("wiki.meta"), XQuery ("xq", "xquery"), YAML ("yaml" , "yml"), Markdown ("md", "markdown"), formats ("json", "xml" , "proto"), "regex"

Didn't found yours? Please, open issue to show your interest & I'll try to add this language in next releases.

List of available themes

Issues

  • Lack of themes

compose-code-editor's People

Contributors

esafirm avatar kbiakov avatar wakaztahir avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

compose-code-editor's Issues

Text input does not work

When using a virtual keyboard, text input does not work. Although when using a physical one in the emulator, everything is fine.

Publish

  • Publish To Github Packages
  • Publish To Jitpack

Crashing with null language providers

I'm trying to show XML but I keep running into:

Exception in thread "AWT-EventQueue-0" java.lang.IllegalArgumentException: Missing language for extension : 
	at com.wakaztahir.codeeditor.prettify.parser.Prettify.getLangFromExtension(Prettify.kt:137)
	at com.wakaztahir.codeeditor.prettify.parser.Prettify.getLexerForExtension(Prettify.kt:404)
	at com.wakaztahir.codeeditor.prettify.parser.Prettify$CreateSimpleLexer.decorate(Prettify.kt:792)
	at com.wakaztahir.codeeditor.prettify.PrettifyParser.parse(PrettifyParser.kt:25)
	at com.wakaztahir.codeeditor.prettify.PrettifyParser.parse(PrettifyParser.kt:21)

Following "Android Only" tries to import JS

Adding this to an Android project:

implementation("com.github.qawaz:compose-code-editor:3.1.1")

Results in this error:

Could not determine the dependencies of task ':app:lintVitalReportDebug'.
> Could not resolve all task dependencies for configuration ':app:debugCompileClasspath'.
   > Could not resolve com.github.qawaz.compose-code-editor:codeeditor-js:3.1.1.
     Required by:
         project :app > com.github.qawaz:compose-code-editor:3.1.1
      > No matching variant of com.github.qawaz.compose-code-editor:codeeditor-js:3.1.1 was found. The consumer was configured to find a library for use during compile-time, preferably optimized for Android, as well as attribute 'com.android.build.api.attributes.BuildTypeAttr' with value 'debug', attribute 'com.android.build.api.attributes.AgpVersionAttr' with value '8.2.2', attribute 'org.jetbrains.kotlin.platform.type' with value 'androidJvm' but:
          - Variant 'jsApiElements-published' capability com.github.qawaz.compose-code-editor:codeeditor-js:3.1.1 declares a library:
              - Incompatible because this component declares a component for use during 'kotlin-api', as well as attribute 'org.jetbrains.kotlin.platform.type' with value 'js' and the consumer needed a component for use during compile-time, as well as attribute 'org.jetbrains.kotlin.platform.type' with value 'androidJvm'
              - Other compatible attributes:

Allow extending Lang

Currently shortcutStylePatterns / fallthroughStylePatterns is internal, this doesnt allow extending with our own language without adding it here, is it intentional?

Dependency error

I added this to my jetpack compose desktop project:

build.gradle.kts:

repositories {
    maven {
        name = "GitHubPackages"
        url = uri("https://maven.pkg.github.com/codeckle/compose-code-editor")
        credentials {
            username = (githubProperties["gpr.usr"] ?: System.getenv("GPR_USER")).toString()
            password = (githubProperties["gpr.key"] ?: System.getenv("GPR_API_KEY")).toString()
        }
    }
}

dependencies {
    implementation("com.wakaztahir.codeeditor:3.0.3")
    implementation("com.wakaztahir.codeeditor-desktop:3.0.3")
 }

github.properties:

gpr.usr=LartyHD
gpr.key=MY_GITHUB_ACCESS_TOKEN_WITH_'read:packages'_PERMISSIONS

and I get this error:

> Task :compileKotlinJvm FAILED

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':compileKotlinJvm'.
> Error while evaluating property 'filteredArgumentsMap' of task ':compileKotlinJvm'
   > Could not resolve all files for configuration ':jvmCompileClasspath'.
      > Could not find com.wakaztahir.codeeditor:3.0.3:.
        Required by:
            project :
      > Could not find com.wakaztahir.codeeditor-desktop:3.0.3:.
        Required by:
            project :

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.