Skip to content

Commit 4b6e761

Browse files
committed
Code cleanup
1 parent 71587d8 commit 4b6e761

File tree

2 files changed

+154
-175
lines changed

2 files changed

+154
-175
lines changed

codeview/src/main/java/io/github/kbiakov/codeview/highlight/CodeHighlighter.kt

Lines changed: 50 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -13,47 +13,32 @@ import java.util.*
1313
*/
1414
object CodeHighlighter {
1515

16-
private val LT_BRACE = "<".toRegex()
17-
private const val LT_REGULAR = "&lt;"
18-
private const val LT_TMP = "^"
19-
20-
private val parser = PrettifyParser()
21-
2216
/**
2317
* Highlight code content.
2418
*
25-
* @param codeLanguage Programming language
26-
* @param rawSource Code source by one string
27-
* @param colorTheme Color theme (see below)
19+
* @param language Programming language
20+
* @param source Source code as single string
21+
* @param theme Color theme (see below)
2822
* @return Highlighted code, string with necessary inserted color tags
2923
*/
30-
fun highlight(codeLanguage: String, rawSource: String, colorTheme: ColorThemeData): String {
31-
val source = rawSource.escapeLT()
32-
val results = parser.parse(codeLanguage, source)
33-
val colorsMap = buildColorsMap(colorTheme)
34-
val highlighted = StringBuilder()
35-
36-
results.forEach {
37-
val color = colorsMap.getColor(it)
38-
val content = parseContent(source, it)
39-
highlighted.append(content.withFontParams(color))
40-
}
41-
return highlighted.toString()
24+
fun highlight(language: String, source: String, theme: ColorThemeData): String {
25+
val colors = buildColorsMap(theme)
26+
27+
return PrettifyParser().parse(language, source)
28+
.map { source highlight it applyFontParams colors[it] }
29+
.reduce(String::plus)
4230
}
4331

4432
// - Helpers
4533

4634
/**
4735
* Parse user input by extracting highlighted content.
4836
*
49-
* @param codeContent Code content
5037
* @param result Syntax unit
5138
* @return Parsed content to highlight
5239
*/
53-
private fun parseContent(codeContent: String, result: ParseResult): String {
54-
val length = result.offset + result.length
55-
val content = codeContent.substring(result.offset, length)
56-
return content.expandLT()
40+
private infix fun String.highlight(result: ParseResult) = safeLT {
41+
substring(result.offset, result.offset + result.length)
5742
}
5843

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

6853
/**
@@ -71,31 +56,30 @@ object CodeHighlighter {
7156
* @param colorTheme Color theme
7257
* @return Colors map built from color theme
7358
*/
74-
private fun buildColorsMap(colorTheme: ColorThemeData) =
75-
object : HashMap<String, String>() {
76-
init {
77-
val syntaxColors = colorTheme.syntaxColors
78-
79-
put("typ", syntaxColors.type.hex())
80-
put("kwd", syntaxColors.keyword.hex())
81-
put("lit", syntaxColors.literal.hex())
82-
put("com", syntaxColors.comment.hex())
83-
put("str", syntaxColors.string.hex())
84-
put("pun", syntaxColors.punctuation.hex())
85-
put("pln", syntaxColors.plain.hex())
86-
put("tag", syntaxColors.tag.hex())
87-
put("dec", syntaxColors.declaration.hex())
88-
put("src", syntaxColors.plain.hex())
89-
put("atn", syntaxColors.attrName.hex())
90-
put("atv", syntaxColors.attrValue.hex())
91-
put("nocode", syntaxColors.plain.hex())
92-
}
93-
}
94-
95-
// - Escaping/extracting "lower then" symbol
96-
97-
private fun String.escapeLT() = replace(LT_BRACE, LT_TMP)
98-
private fun String.expandLT() = replace(LT_TMP, LT_REGULAR)
59+
private fun buildColorsMap(theme: ColorThemeData): HashMap<String, String> {
60+
fun color(body: SyntaxColors.() -> Int) =
61+
theme.syntaxColors.let { body(it).hex() }
62+
return hashMapOf(
63+
"typ" to color { type },
64+
"kwd" to color { keyword },
65+
"lit" to color { literal },
66+
"com" to color { comment },
67+
"str" to color { string },
68+
"pun" to color { punctuation },
69+
"pln" to color { plain },
70+
"tag" to color { tag },
71+
"dec" to color { declaration },
72+
"src" to color { plain },
73+
"atn" to color { attrName },
74+
"atv" to color { attrValue },
75+
"nocode" to color { plain })
76+
}
77+
78+
// - Escaping/extracting "less then" symbol
79+
80+
private fun String.safeLT(op: String.() -> String) = escapeLT().op().expandLT()
81+
private fun String.escapeLT() = replace("<", "^")
82+
private fun String.expandLT() = replace("^", "&lt;")
9983
}
10084

10185
/**
@@ -222,8 +206,6 @@ enum class Font {
222206

223207
// - Helpers
224208

225-
const val transparent = "#00000000"
226-
227209
/**
228210
* @return Converted hex int to color by adding alpha-channel
229211
*/
@@ -242,50 +224,47 @@ fun Int.hex() = "#${Integer.toHexString(this)}"
242224
* @return Is value equals to found or not condition
243225
*/
244226
fun Int.isFound() = this >= 0
245-
246227
fun Int.notFound() = this == -1
247228

248229
/**
249230
* Apply font params to string.
250231
*
251-
* @param color Color as formatter string
252-
* @return Formatted string
232+
* @param color Color
233+
* @return Parametrized string
253234
*/
254-
fun String.withFontParams(color: String?): String {
255-
val parametrizedString = StringBuilder()
256-
235+
infix fun String.applyFontParams(color: String?): String {
236+
var parametrizedString = ""
257237
var idx = 0
258238
var newIdx = indexOf("\n")
259239

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

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

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

273252
if (idx != indexOf("\n")) // if not replaced only once (for multiline tag coverage)
274-
parametrizedString.append(substring(idx).inFontTag(color))
253+
parametrizedString += substring(idx) inFontTag color
275254
}
276-
return parametrizedString.toString()
255+
return parametrizedString
277256
}
278257

258+
/**
259+
* @return String wrapped in font tag
260+
*/
261+
private infix fun String.inFontTag(color: String?) =
262+
"<font color=\"$color\">${escLineBreakAtStart()}</font>"
263+
279264
/**
280265
* @return String with escaped line break at start
281266
*/
282267
fun String.escLineBreakAtStart() =
283268
if (startsWith("\n") && length >= 1)
284269
substring(1)
285270
else this
286-
287-
/**
288-
* @return String surrounded by font tag
289-
*/
290-
fun String.inFontTag(color: String?) =
291-
"<font color=\"$color\">${escLineBreakAtStart()}</font>"

0 commit comments

Comments
 (0)