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
You can either get this from github packages or jitpack, Please note that Jitpack is android only.
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()
            }
        }
    }
}Create github.properties file in your project at root level and add two properties (make github personal access token)
gpr.usr=yourgithubusername
gpr.key=yourgithubpersonalaccesstokenOr 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.
implementation("com.wakaztahir:codeeditor:3.0.5")allprojects {
    repositories {
        maven { url 'https://jitpack.io' }
    }
}dependencies {
    implementation 'com.github.qawaz:compose-code-editor:2.0.3'
}// 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() }// 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)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
      )
    )
  }
)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) }
        }
    )
}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.
- Default
- Monokai
- Lack of themes
