added clamp function and extensions, fixed bug in range coloring

This commit is contained in:
sergeych committed 2026-01-18 07:18:51 +03:00
1 parent 0759346e4b
commit 5dc2159024
9 files changed
+205 -16

No files matched your search

@@ -139,7 +139,7 @@ class LyngDocumentationProvider : AbstractDocumentationProvider() {
val e: Int = miniSource.offsetOf(d.range.end)
if (offset >= s && offset <= e) {
// For enum constant, we don't have detailed docs in MiniAst yet, but we can render a title
return "<div class='doc-title'>enum constant ${d.name}.${name}</div>"
return renderTitle("enum constant ${d.name}.${name}")
}
}
}
@@ -361,7 +361,7 @@ class LyngDocumentationProvider : AbstractDocumentationProvider() {
"Print values to the standard output and append a newline. Accepts any number of arguments." else
"Print values to the standard output without a trailing newline. Accepts any number of arguments."
val title = "function $ident(values)"
return "<div class='doc-title'>${htmlEscape(title)}</div>" + styledMarkdown(htmlEscape(fallback))
return renderTitle(title) + styledMarkdown(htmlEscape(fallback))
}
// 4b) try class members like ClassName.member with inheritance fallback
val lhs = previousWordBefore(text, idRange.startOffset)
@@ -519,7 +519,7 @@ class LyngDocumentationProvider : AbstractDocumentationProvider() {
}
}
val sb = StringBuilder()
sb.append("<div class='doc-title'>").append(htmlEscape(title)).append("</div>")
sb.append(renderTitle(title))
sb.append(renderDocBody(d.doc))
return sb.toString()
}
@@ -527,7 +527,7 @@ class LyngDocumentationProvider : AbstractDocumentationProvider() {
private fun renderParamDoc(fn: MiniFunDecl, p: MiniParam): String {
val title = "parameter ${p.name}${typeOf(p.type)} in ${fn.name}${signatureOf(fn)}"
val sb = StringBuilder()
sb.append("<div class='doc-title'>").append(htmlEscape(title)).append("</div>")
sb.append(renderTitle(title))
// Find matching @param tag
fn.doc?.tags?.get("param")?.forEach { tag ->
@@ -549,7 +549,7 @@ class LyngDocumentationProvider : AbstractDocumentationProvider() {
val staticStr = if (m.isStatic) "static " else ""
val title = "${staticStr}method $className.${m.name}(${params})${ret}"
val sb = StringBuilder()
sb.append("<div class='doc-title'>").append(htmlEscape(title)).append("</div>")
sb.append(renderTitle(title))
sb.append(renderDocBody(m.doc))
return sb.toString()
}
@@ -560,7 +560,7 @@ class LyngDocumentationProvider : AbstractDocumentationProvider() {
val staticStr = if (m.isStatic) "static " else ""
val title = "${staticStr}${kind} $className.${m.name}${ts}"
val sb = StringBuilder()
sb.append("<div class='doc-title'>").append(htmlEscape(title)).append("</div>")
sb.append(renderTitle(title))
sb.append(renderDocBody(m.doc))
return sb.toString()
}
@@ -579,6 +579,10 @@ class LyngDocumentationProvider : AbstractDocumentationProvider() {
return "(${params})${ret}"
}
private fun renderTitle(title: String): String {
return "<div class='doc-title' style='margin-bottom: 0.8em;'>${htmlEscape(title)}</div>"
}
private fun htmlEscape(s: String): String = buildString(s.length) {
for (ch in s) append(
when (ch) {
@@ -645,7 +649,7 @@ class LyngDocumentationProvider : AbstractDocumentationProvider() {
private fun renderOverloads(name: String, overloads: List<MiniFunDecl>): String {
val sb = StringBuilder()
sb.append("<div class='doc-title'>Overloads for ").append(htmlEscape(name)).append("</div>")
sb.append(renderTitle("Overloads for $name"))
sb.append("<ul>")
overloads.forEach { fn ->
sb.append("<li><code>")
@@ -121,12 +121,39 @@ class LyngLexer : LexerBase() {
// Number
if (ch.isDigit()) {
// Check for hex: 0x...
if (ch == '0' && i + 1 < endOffset && buffer[i + 1] == 'x') {
i += 2
while (i < endOffset && (buffer[i].isDigit() || buffer[i] in 'a'..'f' || buffer[i] in 'A'..'F')) i++
myTokenEnd = i
myTokenType = LyngTokenTypes.NUMBER
return
}
// Decimal or integer
i++
var hasDot = false
var hasE = false
while (i < endOffset) {
val c = buffer[i]
if (c.isDigit()) { i++; continue }
if (c == '.' && !hasDot) { hasDot = true; i++; continue }
if (c.isDigit() || c == '_') {
i++
continue
}
if (c == '.' && !hasDot && !hasE) {
// Check if it's a fractional part (must be followed by a digit)
if (i + 1 < endOffset && buffer[i + 1].isDigit()) {
hasDot = true
i++
continue
}
}
if ((c == 'e' || c == 'E') && !hasE) {
hasE = true
i++
if (i < endOffset && (buffer[i] == '+' || buffer[i] == '-')) i++
continue
}
break
}
myTokenEnd = i
@@ -161,6 +188,35 @@ class LyngLexer : LexerBase() {
// Punctuation
if (isPunct(ch)) {
i++
// Handle common multi-char operators for better highlighting
when (ch) {
'.' -> {
if (i < endOffset && buffer[i] == '.') {
i++
if (i < endOffset && (buffer[i] == '.' || buffer[i] == '<')) i++
}
}
'=' -> {
if (i < endOffset && (buffer[i] == '=' || buffer[i] == '>' || buffer[i] == '~')) {
i++
if (buffer[i - 1] == '=' && i < endOffset && buffer[i] == '=') i++
}
}
'+', '-', '*', '/', '%', '!', '<', '>', '&', '|', '?', ':', '^' -> {
if (i < endOffset) {
val next = buffer[i]
if (next == '=' || next == ch) {
i++
if (ch == '<' && next == '=' && i < endOffset && buffer[i] == '>') i++
if (ch == '!' && next == '=' && i < endOffset && buffer[i] == '=') i++
} else if (ch == '?' && (next == '.' || next == '[' || next == '(' || next == '{' || next == ':' || next == '?')) {
i++
} else if (ch == '-' && next == '>') {
i++
}
}
}
}
myTokenEnd = i
myTokenType = LyngTokenTypes.PUNCT
return