use alloc::string::String;
use alloc::vec::Vec;
use serde::Serialize;
use serde::de::DeserializeOwned;
use crate::error::{Error, Result};
use crate::host;
#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
pub struct Json(pub String);
impl Json {
pub fn from_value<T: Serialize + ?Sized>(value: &T) -> Result<Self> {
serde_json::to_string(value).map(Self).map_err(Error::json)
}
pub fn parse<T: DeserializeOwned>(&self) -> Result<T> {
serde_json::from_str(&self.0).map_err(Error::json)
}
pub fn as_str(&self) -> &str {
&self.0
}
pub fn into_string(self) -> String {
self.0
}
}
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub enum Target {
All,
Viewers,
Daemons,
Machine(String),
Singleton,
}
pub mod values {
use super::*;
#[derive(Clone, Copy, Debug, Default)]
pub struct Values;
impl Values {
pub fn get<T: DeserializeOwned>(&self, key: &str) -> Result<Option<T>> {
match host::values_get(key)? {
Some(json) => Json(json).parse().map(Some),
None => Ok(None),
}
}
pub fn get_json(&self, key: &str) -> Result<Option<Json>> {
Ok(host::values_get(key)?.map(Json))
}
pub fn set<T: Serialize + ?Sized>(&self, key: &str, value: &T) -> Result<()> {
host::values_set(key, &Json::from_value(value)?.0)
}
pub fn delete(&self, key: &str) -> Result<()> {
host::values_delete(key)
}
pub fn keys(&self, prefix: &str) -> Result<Vec<String>> {
host::values_keys(prefix)
}
pub fn watch(&self, prefix: &str) -> Result<()> {
host::values_watch(prefix)
}
}
}
pub mod live {
use super::*;
#[derive(Clone, Copy, Debug, Default)]
pub struct Live;
impl Live {
pub fn publish<T: Serialize + ?Sized>(&self, key: &str, payload: &T) -> Result<()> {
host::live_publish(key, &Json::from_value(payload)?.0)
}
pub fn delete(&self, key: &str) -> Result<()> {
host::live_delete(key)
}
pub fn subscribe(&self, prefix: &str) -> Result<()> {
host::live_subscribe(prefix)
}
pub fn unsubscribe(&self, prefix: &str) -> Result<()> {
host::live_unsubscribe(prefix)
}
}
}
pub mod events {
use super::*;
#[derive(Clone, Copy, Debug, Default)]
pub struct Events;
impl Events {
pub fn emit<T: Serialize + ?Sized>(
&self,
name: &str,
payload: &T,
to: Target,
) -> Result<()> {
host::events_emit(name, &Json::from_value(payload)?.0, &to)
}
pub fn on(&self, pattern: &str) -> Result<()> {
host::events_on(pattern)
}
pub fn off(&self, pattern: &str) -> Result<()> {
host::events_off(pattern)
}
}
}
pub mod calls {
use super::*;
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct CallId(pub u64);
#[derive(Clone, Copy, Debug, Default)]
pub struct Calls;
impl Calls {
pub fn call<Req: Serialize + ?Sized, Resp: DeserializeOwned>(
&self,
method: &str,
request: &Req,
to: Target,
) -> Result<Resp> {
self.call_json(method, &Json::from_value(request)?, to)?
.parse()
}
pub fn call_json(&self, method: &str, request: &Json, to: Target) -> Result<Json> {
host::call(method, &request.0, &to, None).map(Json)
}
pub fn call_json_timeout(
&self,
method: &str,
request: &Json,
to: Target,
timeout_ms: u32,
) -> Result<Json> {
host::call(method, &request.0, &to, Some(timeout_ms)).map(Json)
}
pub fn send<Req: Serialize + ?Sized>(
&self,
method: &str,
request: &Req,
to: Target,
) -> Result<()> {
host::call_send(method, &Json::from_value(request)?.0, &to)
}
pub fn call_async<Req: Serialize + ?Sized>(
&self,
method: &str,
request: &Req,
to: Target,
) -> Result<CallId> {
host::call_async(method, &Json::from_value(request)?.0, &to, None).map(CallId)
}
pub fn call_async_timeout<Req: Serialize + ?Sized>(
&self,
method: &str,
request: &Req,
to: Target,
timeout_ms: u32,
) -> Result<CallId> {
host::call_async(method, &Json::from_value(request)?.0, &to, Some(timeout_ms))
.map(CallId)
}
}
}
pub mod config {
use super::*;
pub fn get<T: DeserializeOwned>() -> Result<T> {
Json(host::config()).parse()
}
pub fn json() -> Json {
Json(host::config())
}
}
pub mod health {
use super::*;
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
pub enum Health {
#[default]
Ok,
Degraded,
Failed,
}
pub fn set(health: Health, message: &str) {
host::health_set(health, message);
}
pub fn ok() {
set(Health::Ok, "");
}
pub fn degraded(message: &str) {
set(Health::Degraded, message);
}
pub fn failed(message: &str) {
set(Health::Failed, message);
}
}
pub mod secrets {
use super::*;
pub fn get(name: &str) -> Result<Option<String>> {
host::secret(name)
}
}
pub mod account {
use super::*;
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Machine {
pub id: String,
pub name: String,
pub online: bool,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Project {
pub id: String,
pub name: String,
pub machine: String,
pub path: String,
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
pub enum AgentStatus {
#[default]
None,
Working,
Idle,
WaitingForInput,
}
#[derive(Clone, Debug, Default, PartialEq, Eq)]
pub struct Pane {
pub id: String,
pub generation: u64,
pub machine: String,
pub project: Option<String>,
pub title: String,
pub cwd: String,
pub cols: u32,
pub rows: u32,
pub program: Option<String>,
pub agent: Option<String>,
pub agent_status: AgentStatus,
}
#[derive(Clone, Debug, Default, PartialEq, Eq)]
pub struct AccountState {
pub machines: Vec<Machine>,
pub projects: Vec<Project>,
pub panes: Vec<Pane>,
}
pub fn state() -> Result<AccountState> {
host::account_state()
}
pub fn watch() -> Result<()> {
host::account_watch()
}
}
pub mod claims {
use super::*;
#[derive(Clone, Copy, Debug, Default)]
pub struct Claims;
impl Claims {
pub fn claim(&self, key: &str, ttl_ms: u32) -> Result<bool> {
host::claim(key, ttl_ms)
}
pub fn release(&self, key: &str) -> Result<()> {
host::release(key)
}
pub fn once(&self, key: &str, ttl_ms: u32, effect: impl FnOnce()) -> Result<bool> {
let won = self.claim(key, ttl_ms)?;
if won {
effect();
}
Ok(won)
}
}
}
pub mod url {
use super::*;
pub fn open(url: &str) -> Result<()> {
host::url_open(url)
}
}
pub mod view {
use super::*;
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct Theme {
pub fg: u32,
pub bg: u32,
pub recede_fg: u32,
pub recede_bg: u32,
pub accent: u32,
pub palette: [u32; 16],
}
pub const XTERM_PALETTE: [u32; 16] = [
0x000000, 0xcd0000, 0x00cd00, 0xcdcd00, 0x0000ee, 0xcd00cd, 0x00cdcd, 0xe5e5e5, 0x7f7f7f,
0xff0000, 0x00ff00, 0xffff00, 0x5c5cff, 0xff00ff, 0x00ffff, 0xffffff,
];
pub const GRAYED_OUT_PERCENT: u16 = 55;
impl Default for Theme {
fn default() -> Self {
Self {
fg: 0xd0d0d0,
bg: 0x000000,
recede_fg: 0x808080,
recede_bg: 0x101010,
accent: 0x5fafff,
palette: XTERM_PALETTE,
}
}
}
impl Theme {
pub fn recede(&self, rgb: u32, percent: u16) -> u32 {
crate::colour::recede(rgb, self.bg, percent)
}
pub fn ansi(&self, index: u8) -> u32 {
self.palette[usize::from(index & 15)]
}
}
pub fn is_driving() -> bool {
host::is_driving()
}
pub fn theme() -> Theme {
host::theme()
}
pub fn focused_pane() -> Option<String> {
host::focused_pane()
}
#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
pub struct PaneRef {
pub id: String,
pub generation: u64,
}
impl PaneRef {
pub fn key(&self) -> String {
alloc::format!("{}@{}", self.id, self.generation)
}
}
pub fn surface_pane(surface: &str) -> Option<PaneRef> {
host::surface_pane(surface)
}
pub fn surface_machine(surface: &str) -> Option<String> {
host::surface_machine(surface)
}
pub fn surface_project(surface: &str) -> Option<String> {
host::surface_project(surface)
}
pub fn surface_tint(surface: &str) -> Option<u32> {
host::surface_tint(surface)
}
pub fn identity_tint(id: &str) -> Option<u32> {
host::identity_tint(id)
}
pub fn machine_id() -> Option<String> {
host::machine_id()
}
pub fn instance_id() -> String {
host::instance_id()
}
pub fn wall_ms() -> u64 {
host::wall_ms()
}
pub fn utc_offset_minutes() -> i32 {
host::utc_offset_minutes()
}
pub fn time_zone() -> Option<String> {
host::time_zone()
}
pub fn local_ms() -> i64 {
host::wall_ms() as i64 + i64::from(host::utc_offset_minutes()) * 60_000
}
}
pub mod capabilities {
use super::*;
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
pub struct Capabilities {
pub graphics: bool,
pub kitty: bool,
pub frame_rate: u32,
pub cell_px: (u32, u32),
pub pixel_scale: u32,
}
pub fn get() -> Capabilities {
host::capabilities()
}
}
pub fn values() -> values::Values {
values::Values
}
pub fn live() -> live::Live {
live::Live
}
pub fn events() -> events::Events {
events::Events
}
pub fn calls() -> calls::Calls {
calls::Calls
}
pub fn claims() -> claims::Claims {
claims::Claims
}