Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion codeview/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
xmlns:android="http://schemas.android.com/apk/res/android">

<application
android:allowBackup="true"
android:label="@string/app_name"
android:supportsRtl="true">

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,47 +13,32 @@ import java.util.*
*/
object CodeHighlighter {

private val LT_BRACE = "<".toRegex()
private const val LT_REGULAR = "&lt;"
private const val LT_TMP = "^"

private val parser = PrettifyParser()

/**
* Highlight code content.
*
* @param codeLanguage Programming language
* @param rawSource Code source by one string
* @param colorTheme Color theme (see below)
* @param language Programming language
* @param source Source code as single string
* @param theme Color theme (see below)
* @return Highlighted code, string with necessary inserted color tags
*/
fun highlight(codeLanguage: String, rawSource: String, colorTheme: ColorThemeData): String {
val source = rawSource.escapeLT()
val results = parser.parse(codeLanguage, source)
val colorsMap = buildColorsMap(colorTheme)
val highlighted = StringBuilder()

results.forEach {
val color = colorsMap.getColor(it)
val content = parseContent(source, it)
highlighted.append(content.withFontParams(color))
}
return highlighted.toString()
fun highlight(language: String, source: String, theme: ColorThemeData): String {
val colors = buildColorsMap(theme)

return PrettifyParser().parse(language, source)
.map { source highlight it applyFontParams colors[it] }
.reduce(String::plus)
}

// - Helpers

/**
* Parse user input by extracting highlighted content.
* Parse input by extracting highlighted content.
*
* @param codeContent Code content
* @param result Syntax unit
* @return Parsed content to highlight
* @return Content to highlight
*/
private fun parseContent(codeContent: String, result: ParseResult): String {
val length = result.offset + result.length
val content = codeContent.substring(result.offset, length)
return content.expandLT()
private infix fun String.highlight(result: ParseResult) = safeLT {
substring(result.offset, result.offset + result.length)
}

/**
Expand All @@ -62,7 +47,7 @@ object CodeHighlighter {
* @param result Syntax unit
* @return Color for syntax unit
*/
private fun HashMap<String, String>.getColor(result: ParseResult) =
private operator fun HashMap<String, String>.get(result: ParseResult) =
this[result.styleKeys[0]] ?: this["pln"]

/**
Expand All @@ -71,31 +56,30 @@ object CodeHighlighter {
* @param colorTheme Color theme
* @return Colors map built from color theme
*/
private fun buildColorsMap(colorTheme: ColorThemeData) =
object : HashMap<String, String>() {
init {
val syntaxColors = colorTheme.syntaxColors

put("typ", syntaxColors.type.hex())
put("kwd", syntaxColors.keyword.hex())
put("lit", syntaxColors.literal.hex())
put("com", syntaxColors.comment.hex())
put("str", syntaxColors.string.hex())
put("pun", syntaxColors.punctuation.hex())
put("pln", syntaxColors.plain.hex())
put("tag", syntaxColors.tag.hex())
put("dec", syntaxColors.declaration.hex())
put("src", syntaxColors.plain.hex())
put("atn", syntaxColors.attrName.hex())
put("atv", syntaxColors.attrValue.hex())
put("nocode", syntaxColors.plain.hex())
}
}

// - Escaping/extracting "lower then" symbol

private fun String.escapeLT() = replace(LT_BRACE, LT_TMP)
private fun String.expandLT() = replace(LT_TMP, LT_REGULAR)
private fun buildColorsMap(theme: ColorThemeData): HashMap<String, String> {
fun color(body: SyntaxColors.() -> Int) =
theme.syntaxColors.let { body(it).hex() }
return hashMapOf(
"typ" to color { type },
"kwd" to color { keyword },
"lit" to color { literal },
"com" to color { comment },
"str" to color { string },
"pun" to color { punctuation },
"pln" to color { plain },
"tag" to color { tag },
"dec" to color { declaration },
"src" to color { plain },
"atn" to color { attrName },
"atv" to color { attrValue },
"nocode" to color { plain })
}

// - Escaping/extracting "less then" symbol

private fun String.safeLT(op: String.() -> String) = escapeLT().op().expandLT()
private fun String.escapeLT() = replace("<", "^")
private fun String.expandLT() = replace("^", "&lt;")
}

/**
Expand Down Expand Up @@ -222,8 +206,6 @@ enum class Font {

// - Helpers

const val transparent = "#00000000"

/**
* @return Converted hex int to color by adding alpha-channel
*/
Expand All @@ -242,50 +224,47 @@ fun Int.hex() = "#${Integer.toHexString(this)}"
* @return Is value equals to found or not condition
*/
fun Int.isFound() = this >= 0

fun Int.notFound() = this == -1

/**
* Apply font params to string.
*
* @param color Color as formatter string
* @return Formatted string
* @param color Color
* @return Parametrized string
*/
fun String.withFontParams(color: String?): String {
val parametrizedString = StringBuilder()

infix fun String.applyFontParams(color: String?): String {
var parametrizedString = ""
var idx = 0
var newIdx = indexOf("\n")

if (newIdx.notFound()) // covers expected tag coverage (within only one line)
parametrizedString.append(inFontTag(color))
parametrizedString += inFontTag(color)
else { // may contain multiple lines with line breaks

// put tag on the borders (end & start of line, ..., end of tag)
do { // until closing tag is reached
val part = substring(idx .. newIdx - 1).inFontTag(color).plus("\n")
parametrizedString.append(part)
parametrizedString += (substring(idx .. newIdx - 1) inFontTag color) + "\n"

idx = newIdx + 1
newIdx = indexOf("\n", idx)
} while (newIdx.isFound())

if (idx != indexOf("\n")) // if not replaced only once (for multiline tag coverage)
parametrizedString.append(substring(idx).inFontTag(color))
parametrizedString += substring(idx) inFontTag color
}
return parametrizedString.toString()
return parametrizedString
}

/**
* @return String wrapped in font tag
*/
private infix fun String.inFontTag(color: String?) =
"<font color=\"$color\">${escLineBreakAtStart()}</font>"

/**
* @return String with escaped line break at start
*/
fun String.escLineBreakAtStart() =
if (startsWith("\n") && length >= 1)
substring(1)
else this

/**
* @return String surrounded by font tag
*/
fun String.inFontTag(color: String?) =
"<font color=\"$color\">${escLineBreakAtStart()}</font>"
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,12 @@ import io.github.kbiakov.codeview.highlight.FontCache
*
* @author Kirill Biakov
*/
class LineDiffView : RelativeLayout {
class LineDiffView(context: Context) : RelativeLayout(context) {

private val tvLineDiff: TextView
private val tvLineContent: TextView

/**
* Default constructor.
*/
constructor(context: Context) : super(context) {
init {
val inflater = context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
inflater.inflate(R.layout.item_code_diff, this, true)

Expand All @@ -39,19 +36,16 @@ class LineDiffView : RelativeLayout {
* @param model Diff model
* @return Created line diff view
*/
fun create(context: Context, model: DiffModel): LineDiffView {
val diffView = LineDiffView(context)
diffView.tvLineDiff.text = if (model.isAddition) "+" else "-"
diffView.tvLineContent.text = model.content
diffView.tvLineContent.typeface = FontCache.get(context).getTypeface(context)
fun create(context: Context, model: DiffModel) = LineDiffView(context).apply {
tvLineDiff.text = if (model.isAddition) "+" else "-"
tvLineContent.text = model.content
tvLineContent.typeface = FontCache.get(context).getTypeface(context)

diffView.setBackgroundColor(ContextCompat.getColor(context,
setBackgroundColor(ContextCompat.getColor(context,
if (model.isAddition)
R.color.diff_add_background
else
R.color.diff_del_background))

return diffView
}
}
}
Expand Down
9 changes: 4 additions & 5 deletions codeview/src/main/res/layout/item_code_diff.xml
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,19 @@
android:layout_width="@dimen/line_num_width"
android:layout_height="@dimen/line_height"
android:gravity="center"
android:fontFamily="monospace"
android:textSize="@dimen/line_text_size"
android:text="@string/stub_line_num"/>

<TextView
android:id="@+id/tv_line_content"
android:layout_width="wrap_content"
android:layout_height="@dimen/line_height"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:layout_marginLeft="@dimen/default_margin"
android:layout_marginRight="@dimen/default_margin"
android:layout_toEndOf="@+id/tv_line_diff"
android:layout_toRightOf="@+id/tv_line_diff"
android:gravity="center_vertical"
android:fontFamily="monospace"
android:singleLine="true"
android:maxLines="1"
android:textSize="@dimen/line_text_size"
android:text="@string/stub_line_content"/>

Expand Down
5 changes: 3 additions & 2 deletions codeview/src/main/res/layout/item_code_line.xml
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,9 @@
android:id="@+id/tv_line_content"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:layout_marginLeft="@dimen/default_margin"
android:layout_marginRight="@dimen/default_margin"
android:layout_toEndOf="@+id/tv_line_num"
android:layout_toRightOf="@+id/tv_line_num"
android:gravity="center_vertical"
android:maxLines="1"
Expand Down
1 change: 1 addition & 0 deletions codeview/src/main/res/layout/layout_code_view.xml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
android:id="@+id/shadow_right_border"
android:layout_width="@dimen/shadow_width"
android:layout_height="match_parent"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"/>

<LinearLayout
Expand Down
6 changes: 0 additions & 6 deletions codeview/src/main/res/values/colors.xml
Original file line number Diff line number Diff line change
@@ -1,11 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="code_num">#99a8b7</color>
<color name="code_num_background">#f2f2f6</color>
<color name="code_content">#2c2d30</color>
<color name="code_content_background">#e9edf4</color>
<color name="note">#4c5d6e</color>

<color name="diff_add_background">#EAFFEA</color>
<color name="diff_del_background">#FFECEC</color>
</resources>
1 change: 1 addition & 0 deletions codeview/src/main/res/values/dimens.xml
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<dimen name="default_margin">16dp</dimen>
<dimen name="line_num_width">32dp</dimen>
<dimen name="line_height">24dp</dimen>
<dimen name="line_border_height">4dp</dimen>
Expand Down
4 changes: 2 additions & 2 deletions example/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ android {
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
sourceSets {
main.java.srcDirs += 'src/main/kotlin'
lintOptions {
abortOnError false
}
}

Expand Down
3 changes: 1 addition & 2 deletions example/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

<application
android:name=".BaseApplication"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
Expand All @@ -19,4 +18,4 @@

</application>

</manifest>
</manifest>
Loading