// Syntax service for token data API.
//
// Philosophy: Server provides token categories (mechanism).
// Client applies colors based on theme (policy).
// No color data in protocol - only semantic categories.

syntax = "proto3";
package reovim.v2;

service SyntaxService {
  // Get syntax tokens for a buffer range (one-shot query).
  // Use for initial buffer load or after major edits.
  rpc GetTokens(GetTokensRequest) returns (GetTokensResponse);

  // Stream token updates in real-time.
  // Emits updates when buffer content changes.
  rpc StreamTokens(StreamTokensRequest) returns (stream TokenUpdate);

  // Get language info for a buffer.
  // Returns language ID, name, and parser availability.
  rpc GetLanguageInfo(GetLanguageInfoRequest) returns (GetLanguageInfoResponse);
}

// ─────────────────────────────────────────────────────────────────────
// GetTokens - One-shot token query
// ─────────────────────────────────────────────────────────────────────

message GetTokensRequest {
  uint64 buffer_id = 1;
  optional uint64 start_line = 2;  // Default: 0
  optional uint64 end_line = 3;    // Default: end of buffer
}

message GetTokensResponse {
  uint64 buffer_id = 1;
  repeated TokenSpan tokens = 2;
  string language_id = 3;          // e.g., "rust", "typescript"
  uint64 total_lines = 4;
}

// A syntax token with byte range and category.
//
// Uses byte offsets for efficient incremental updates.
// Category strings follow TextMate/tree-sitter naming:
// - "keyword", "keyword.control", "keyword.function"
// - "function", "function.builtin", "function.macro"
// - "variable", "variable.builtin", "variable.parameter"
// - "string", "string.escape"
// - "comment", "comment.doc"
// - "type", "type.builtin"
// - "operator", "punctuation", "punctuation.bracket"
//
// Note: Field 4 (AnnotationKind kind) was retired in #551.
// Never reuse field number 4. Clients that receive old messages
// with field 4 will safely ignore it (proto3 unknown field behavior).
message TokenSpan {
  uint32 start_byte = 1;
  uint32 end_byte = 2;
  string category = 3;            // e.g., "keyword", "function", "string"
  // Field 4 retired: was `optional AnnotationKind kind = 4`
}

// ─────────────────────────────────────────────────────────────────────
// StreamTokens - Real-time token updates
// ─────────────────────────────────────────────────────────────────────

message StreamTokensRequest {
  uint64 buffer_id = 1;
}

// Token update notification.
// Sent when buffer content changes affect syntax tokens.
message TokenUpdate {
  uint64 buffer_id = 1;
  repeated TokenSpan tokens = 2;
  uint64 start_line = 3;           // Affected range start
  uint64 end_line = 4;             // Affected range end
  bool full_refresh = 5;           // If true, replace all cached tokens
  string layer = 6;               // Layer name: "syntax", "lsp.semantic", etc.
  uint32 priority = 7;            // Layer priority (higher = on top)
}

// ─────────────────────────────────────────────────────────────────────
// GetLanguageInfo - Language metadata
// ─────────────────────────────────────────────────────────────────────

message GetLanguageInfoRequest {
  uint64 buffer_id = 1;
}

message GetLanguageInfoResponse {
  string language_id = 1;          // e.g., "rust", "python"
  string language_name = 2;        // e.g., "Rust", "Python"
  repeated string extensions = 3;  // e.g., [".rs"], [".py", ".pyi"]
  bool has_parser = 4;             // true if tree-sitter parser available
}
