git.iko.soy/opencode-android
on 066cded help sign in
90 lines 2.9 kB history raw
1package soy.iko.opencode.data.model
3import androidx.compose.runtime.Immutable
4import kotlinx.serialization.SerialName
5import kotlinx.serialization.Serializable
7/**
8 * One ripgrep match from `GET /find?pattern=` (content search). [path] and [lines] are
9 * wrapped `{ text }` objects on the wire; [submatches] carry the column offsets of each
10 * hit within the line so the UI can highlight them.
11 */
12@Immutable
13@Serializable
14data class FindMatch(
15 val path: TextField = TextField(),
16 val lines: TextField = TextField(),
17 @SerialName("line_number") val lineNumber: Int = 0,
18 @SerialName("absolute_offset") val absoluteOffset: Long = 0,
19 val submatches: List<SubMatch> = emptyList(),
20) {
21 @Immutable
22 @Serializable
23 data class TextField(val text: String = "")
25 @Immutable
26 @Serializable
27 data class SubMatch(
28 val start: Int = 0,
29 val end: Int = 0,
30 )
32 /** The matched file's path (relative to the search root). */
33 val filePath: String get() = path.text
35 /** The matching line's text, trimmed of a trailing newline for display. */
36 val lineText: String get() = lines.text.trimEnd('\n', '\r')
39/**
40 * One workspace symbol from `GET /find/symbol?query=`. [kind] is the LSP `SymbolKind`
41 * integer; [location.uri] is a file URI and [location.range] the symbol's span.
42 */
43@Immutable
44@Serializable
45data class SymbolResult(
46 val name: String = "",
47 val kind: Int = 0,
48 val location: Location = Location(),
49) {
50 @Immutable
51 @Serializable
52 data class Location(
53 val uri: String = "",
54 val range: Range = Range(),
55 )
57 @Immutable
58 @Serializable
59 data class Range(
60 val start: Pos = Pos(),
61 val end: Pos = Pos(),
62 )
64 @Immutable
65 @Serializable
66 data class Pos(
67 val line: Int = 0,
68 val character: Int = 0,
69 )
71 /** The file path portion of [Location.uri], stripping a `file://` scheme when present. */
72 val filePath: String
73 get() = location.uri.removePrefix("file://").ifBlank { location.uri }
75 /** 1-based line for display; the wire range is 0-based. */
76 val displayLine: Int get() = location.range.start.line + 1
79// LSP SymbolKind → label. A map lookup (rather than a large `when`) keeps the accessor
80// trivial. Indices follow the LSP SymbolKind enum.
81private val symbolKindLabels = mapOf(
82 1 to "file", 2 to "module", 3 to "namespace", 4 to "package", 5 to "class",
83 6 to "method", 7 to "property", 8 to "field", 9 to "constructor", 10 to "enum",
84 11 to "interface", 12 to "function", 13 to "variable", 14 to "constant", 15 to "string",
85 16 to "number", 17 to "boolean", 18 to "array", 19 to "object", 20 to "key",
86 22 to "enum member", 23 to "struct", 26 to "type",
89/** Human-readable label for an LSP [SymbolResult.kind]. */
90fun symbolKindLabel(kind: Int): String = symbolKindLabels[kind] ?: "symbol"