mirror of
https://github.com/mountain-loop/yaak.git
synced 2026-04-20 07:51:20 +02:00
Vim/emacs/vscode keybindings
This commit is contained in:
2
src-tauri/migrations/20250108035425_editor-keymap.sql
Normal file
2
src-tauri/migrations/20250108035425_editor-keymap.sql
Normal file
@@ -0,0 +1,2 @@
|
||||
ALTER TABLE settings
|
||||
ADD COLUMN editor_keymap TEXT DEFAULT 'codemirror' NOT NULL;
|
||||
@@ -1,250 +1,61 @@
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
|
||||
export type AnyModel =
|
||||
| CookieJar
|
||||
| Environment
|
||||
| Folder
|
||||
| GrpcConnection
|
||||
| GrpcEvent
|
||||
| GrpcRequest
|
||||
| HttpRequest
|
||||
| HttpResponse
|
||||
| Plugin
|
||||
| Settings
|
||||
| KeyValue
|
||||
| Workspace;
|
||||
export type AnyModel = CookieJar | Environment | Folder | GrpcConnection | GrpcEvent | GrpcRequest | HttpRequest | HttpResponse | Plugin | Settings | KeyValue | Workspace;
|
||||
|
||||
export type Cookie = {
|
||||
raw_cookie: string;
|
||||
domain: CookieDomain;
|
||||
expires: CookieExpires;
|
||||
path: [string, boolean];
|
||||
};
|
||||
export type Cookie = { raw_cookie: string, domain: CookieDomain, expires: CookieExpires, path: [string, boolean], };
|
||||
|
||||
export type CookieDomain = { HostOnly: string } | { Suffix: string } | 'NotPresent' | 'Empty';
|
||||
export type CookieDomain = { "HostOnly": string } | { "Suffix": string } | "NotPresent" | "Empty";
|
||||
|
||||
export type CookieExpires = { AtUtc: string } | 'SessionEnd';
|
||||
export type CookieExpires = { "AtUtc": string } | "SessionEnd";
|
||||
|
||||
export type CookieJar = {
|
||||
model: 'cookie_jar';
|
||||
id: string;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
workspaceId: string;
|
||||
cookies: Array<Cookie>;
|
||||
name: string;
|
||||
};
|
||||
export type CookieJar = { model: "cookie_jar", id: string, createdAt: string, updatedAt: string, workspaceId: string, cookies: Array<Cookie>, name: string, };
|
||||
|
||||
export type Environment = {
|
||||
model: 'environment';
|
||||
id: string;
|
||||
workspaceId: string;
|
||||
environmentId: string | null;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
name: string;
|
||||
variables: Array<EnvironmentVariable>;
|
||||
};
|
||||
export type EditorKeymap = "default" | "vim" | "vscode" | "emacs";
|
||||
|
||||
export type EnvironmentVariable = { enabled?: boolean; name: string; value: string; id: string };
|
||||
export type Environment = { model: "environment", id: string, workspaceId: string, environmentId: string | null, createdAt: string, updatedAt: string, name: string, variables: Array<EnvironmentVariable>, };
|
||||
|
||||
export type Folder = {
|
||||
model: 'folder';
|
||||
id: string;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
workspaceId: string;
|
||||
folderId: string | null;
|
||||
name: string;
|
||||
description: string;
|
||||
sortPriority: number;
|
||||
};
|
||||
export type EnvironmentVariable = { enabled?: boolean, name: string, value: string, id: string, };
|
||||
|
||||
export type GrpcConnection = {
|
||||
model: 'grpc_connection';
|
||||
id: string;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
workspaceId: string;
|
||||
requestId: string;
|
||||
elapsed: number;
|
||||
error: string | null;
|
||||
method: string;
|
||||
service: string;
|
||||
status: number;
|
||||
state: GrpcConnectionState;
|
||||
trailers: { [key in string]?: string };
|
||||
url: string;
|
||||
};
|
||||
export type Folder = { model: "folder", id: string, createdAt: string, updatedAt: string, workspaceId: string, folderId: string | null, name: string, description: string, sortPriority: number, };
|
||||
|
||||
export type GrpcConnectionState = 'initialized' | 'connected' | 'closed';
|
||||
export type GrpcConnection = { model: "grpc_connection", id: string, createdAt: string, updatedAt: string, workspaceId: string, requestId: string, elapsed: number, error: string | null, method: string, service: string, status: number, state: GrpcConnectionState, trailers: { [key in string]?: string }, url: string, };
|
||||
|
||||
export type GrpcEvent = {
|
||||
model: 'grpc_event';
|
||||
id: string;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
workspaceId: string;
|
||||
requestId: string;
|
||||
connectionId: string;
|
||||
content: string;
|
||||
error: string | null;
|
||||
eventType: GrpcEventType;
|
||||
metadata: { [key in string]?: string };
|
||||
status: number | null;
|
||||
};
|
||||
export type GrpcConnectionState = "initialized" | "connected" | "closed";
|
||||
|
||||
export type GrpcEventType =
|
||||
| 'info'
|
||||
| 'error'
|
||||
| 'client_message'
|
||||
| 'server_message'
|
||||
| 'connection_start'
|
||||
| 'connection_end';
|
||||
export type GrpcEvent = { model: "grpc_event", id: string, createdAt: string, updatedAt: string, workspaceId: string, requestId: string, connectionId: string, content: string, error: string | null, eventType: GrpcEventType, metadata: { [key in string]?: string }, status: number | null, };
|
||||
|
||||
export type GrpcMetadataEntry = { enabled?: boolean; name: string; value: string; id: string };
|
||||
export type GrpcEventType = "info" | "error" | "client_message" | "server_message" | "connection_start" | "connection_end";
|
||||
|
||||
export type GrpcRequest = {
|
||||
model: 'grpc_request';
|
||||
id: string;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
workspaceId: string;
|
||||
folderId: string | null;
|
||||
authenticationType: string | null;
|
||||
authentication: Record<string, any>;
|
||||
description: string;
|
||||
message: string;
|
||||
metadata: Array<GrpcMetadataEntry>;
|
||||
method: string | null;
|
||||
name: string;
|
||||
service: string | null;
|
||||
sortPriority: number;
|
||||
url: string;
|
||||
};
|
||||
export type GrpcMetadataEntry = { enabled?: boolean, name: string, value: string, id: string, };
|
||||
|
||||
export type HttpRequest = {
|
||||
model: 'http_request';
|
||||
id: string;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
workspaceId: string;
|
||||
folderId: string | null;
|
||||
authentication: Record<string, any>;
|
||||
authenticationType: string | null;
|
||||
body: Record<string, any>;
|
||||
bodyType: string | null;
|
||||
description: string;
|
||||
headers: Array<HttpRequestHeader>;
|
||||
method: string;
|
||||
name: string;
|
||||
sortPriority: number;
|
||||
url: string;
|
||||
urlParameters: Array<HttpUrlParameter>;
|
||||
};
|
||||
export type GrpcRequest = { model: "grpc_request", id: string, createdAt: string, updatedAt: string, workspaceId: string, folderId: string | null, authenticationType: string | null, authentication: Record<string, any>, description: string, message: string, metadata: Array<GrpcMetadataEntry>, method: string | null, name: string, service: string | null, sortPriority: number, url: string, };
|
||||
|
||||
export type HttpRequestHeader = { enabled?: boolean; name: string; value: string; id: string };
|
||||
export type HttpRequest = { model: "http_request", id: string, createdAt: string, updatedAt: string, workspaceId: string, folderId: string | null, authentication: Record<string, any>, authenticationType: string | null, body: Record<string, any>, bodyType: string | null, description: string, headers: Array<HttpRequestHeader>, method: string, name: string, sortPriority: number, url: string, urlParameters: Array<HttpUrlParameter>, };
|
||||
|
||||
export type HttpResponse = {
|
||||
model: 'http_response';
|
||||
id: string;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
workspaceId: string;
|
||||
requestId: string;
|
||||
bodyPath: string | null;
|
||||
contentLength: number | null;
|
||||
elapsed: number;
|
||||
elapsedHeaders: number;
|
||||
error: string | null;
|
||||
headers: Array<HttpResponseHeader>;
|
||||
remoteAddr: string | null;
|
||||
status: number;
|
||||
statusReason: string | null;
|
||||
state: HttpResponseState;
|
||||
url: string;
|
||||
version: string | null;
|
||||
};
|
||||
export type HttpRequestHeader = { enabled?: boolean, name: string, value: string, id: string, };
|
||||
|
||||
export type HttpResponseHeader = { name: string; value: string };
|
||||
export type HttpResponse = { model: "http_response", id: string, createdAt: string, updatedAt: string, workspaceId: string, requestId: string, bodyPath: string | null, contentLength: number | null, elapsed: number, elapsedHeaders: number, error: string | null, headers: Array<HttpResponseHeader>, remoteAddr: string | null, status: number, statusReason: string | null, state: HttpResponseState, url: string, version: string | null, };
|
||||
|
||||
export type HttpResponseState = 'initialized' | 'connected' | 'closed';
|
||||
export type HttpResponseHeader = { name: string, value: string, };
|
||||
|
||||
export type HttpUrlParameter = { enabled?: boolean; name: string; value: string; id: string };
|
||||
export type HttpResponseState = "initialized" | "connected" | "closed";
|
||||
|
||||
export type KeyValue = {
|
||||
model: 'key_value';
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
key: string;
|
||||
namespace: string;
|
||||
value: string;
|
||||
};
|
||||
export type HttpUrlParameter = { enabled?: boolean, name: string, value: string, id: string, };
|
||||
|
||||
export type ModelPayload = { model: AnyModel; windowLabel: string; updateSource: UpdateSource };
|
||||
export type KeyValue = { model: "key_value", createdAt: string, updatedAt: string, key: string, namespace: string, value: string, };
|
||||
|
||||
export type Plugin = {
|
||||
model: 'plugin';
|
||||
id: string;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
checkedAt: string | null;
|
||||
directory: string;
|
||||
enabled: boolean;
|
||||
url: string | null;
|
||||
};
|
||||
export type ModelPayload = { model: AnyModel, windowLabel: string, updateSource: UpdateSource, };
|
||||
|
||||
export type ProxySetting =
|
||||
| { type: 'enabled'; http: string; https: string; auth: ProxySettingAuth | null }
|
||||
| {
|
||||
type: 'disabled';
|
||||
};
|
||||
export type Plugin = { model: "plugin", id: string, createdAt: string, updatedAt: string, checkedAt: string | null, directory: string, enabled: boolean, url: string | null, };
|
||||
|
||||
export type ProxySettingAuth = { user: string; password: string };
|
||||
export type ProxySetting = { "type": "enabled", http: string, https: string, auth: ProxySettingAuth | null, } | { "type": "disabled" };
|
||||
|
||||
export type Settings = {
|
||||
model: 'settings';
|
||||
id: string;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
appearance: string;
|
||||
editorFontSize: number;
|
||||
editorSoftWrap: boolean;
|
||||
interfaceFontSize: number;
|
||||
interfaceScale: number;
|
||||
openWorkspaceNewWindow: boolean | null;
|
||||
telemetry: boolean;
|
||||
theme: string;
|
||||
themeDark: string;
|
||||
themeLight: string;
|
||||
updateChannel: string;
|
||||
proxy: ProxySetting | null;
|
||||
};
|
||||
export type ProxySettingAuth = { user: string, password: string, };
|
||||
|
||||
export type SyncState = {
|
||||
model: 'sync_state';
|
||||
id: string;
|
||||
workspaceId: string;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
flushedAt: string;
|
||||
modelId: string;
|
||||
checksum: string;
|
||||
relPath: string;
|
||||
syncDir: string;
|
||||
};
|
||||
export type Settings = { model: "settings", id: string, createdAt: string, updatedAt: string, appearance: string, editorFontSize: number, editorSoftWrap: boolean, interfaceFontSize: number, interfaceScale: number, openWorkspaceNewWindow: boolean | null, proxy: ProxySetting | null, telemetry: boolean, theme: string, themeDark: string, themeLight: string, updateChannel: string, editorKeymap: EditorKeymap, };
|
||||
|
||||
export type UpdateSource = 'sync' | 'window' | 'plugin' | 'background';
|
||||
export type SyncState = { model: "sync_state", id: string, workspaceId: string, createdAt: string, updatedAt: string, flushedAt: string, modelId: string, checksum: string, relPath: string, syncDir: string, };
|
||||
|
||||
export type Workspace = {
|
||||
model: 'workspace';
|
||||
id: string;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
name: string;
|
||||
description: string;
|
||||
settingValidateCertificates: boolean;
|
||||
settingFollowRedirects: boolean;
|
||||
settingRequestTimeout: number;
|
||||
settingSyncDir: string | null;
|
||||
};
|
||||
export type UpdateSource = "sync" | "window" | "plugin" | "background";
|
||||
|
||||
export type Workspace = { model: "workspace", id: string, createdAt: string, updatedAt: string, name: string, description: string, settingValidateCertificates: boolean, settingFollowRedirects: boolean, settingRequestTimeout: number, settingSyncDir: string | null, };
|
||||
|
||||
@@ -4,6 +4,8 @@ use sea_query::Iden;
|
||||
use serde::{Deserialize, Deserializer, Serialize};
|
||||
use serde_json::Value;
|
||||
use std::collections::BTreeMap;
|
||||
use std::fmt::Display;
|
||||
use std::str::FromStr;
|
||||
use ts_rs::TS;
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, TS)]
|
||||
@@ -26,6 +28,48 @@ pub struct ProxySettingAuth {
|
||||
pub password: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, TS)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
#[ts(export, export_to = "models.ts")]
|
||||
pub enum EditorKeymap {
|
||||
Default,
|
||||
Vim,
|
||||
Vscode,
|
||||
Emacs,
|
||||
}
|
||||
|
||||
impl FromStr for EditorKeymap {
|
||||
type Err = ();
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
match s {
|
||||
"default" => Ok(Self::Default),
|
||||
"vscode" => Ok(Self::Vscode),
|
||||
"vim" => Ok(Self::Vim),
|
||||
"emacs" => Ok(Self::Emacs),
|
||||
_ => Ok(Self::default()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for EditorKeymap {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
let str = match self {
|
||||
EditorKeymap::Default => "default".to_string(),
|
||||
EditorKeymap::Vscode => "vscode".to_string(),
|
||||
EditorKeymap::Vim => "vim".to_string(),
|
||||
EditorKeymap::Emacs => "emacs".to_string(),
|
||||
};
|
||||
write!(f, "{}", str)
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for EditorKeymap {
|
||||
fn default() -> Self {
|
||||
Self::Default
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, Default, TS)]
|
||||
#[serde(default, rename_all = "camelCase")]
|
||||
#[ts(export, export_to = "models.ts")]
|
||||
@@ -42,12 +86,13 @@ pub struct Settings {
|
||||
pub interface_font_size: i32,
|
||||
pub interface_scale: f32,
|
||||
pub open_workspace_new_window: Option<bool>,
|
||||
pub proxy: Option<ProxySetting>,
|
||||
pub telemetry: bool,
|
||||
pub theme: String,
|
||||
pub theme_dark: String,
|
||||
pub theme_light: String,
|
||||
pub update_channel: String,
|
||||
pub proxy: Option<ProxySetting>,
|
||||
pub editor_keymap: EditorKeymap,
|
||||
}
|
||||
|
||||
#[derive(Iden)]
|
||||
@@ -61,6 +106,7 @@ pub enum SettingsIden {
|
||||
|
||||
Appearance,
|
||||
EditorFontSize,
|
||||
EditorKeymap,
|
||||
EditorSoftWrap,
|
||||
InterfaceFontSize,
|
||||
InterfaceScale,
|
||||
@@ -78,6 +124,7 @@ impl<'s> TryFrom<&Row<'s>> for Settings {
|
||||
|
||||
fn try_from(r: &Row<'s>) -> Result<Self, Self::Error> {
|
||||
let proxy: Option<String> = r.get("proxy")?;
|
||||
let editor_keymap: String = r.get("editor_keymap")?;
|
||||
Ok(Settings {
|
||||
id: r.get("id")?,
|
||||
model: r.get("model")?,
|
||||
@@ -85,6 +132,7 @@ impl<'s> TryFrom<&Row<'s>> for Settings {
|
||||
updated_at: r.get("updated_at")?,
|
||||
appearance: r.get("appearance")?,
|
||||
editor_font_size: r.get("editor_font_size")?,
|
||||
editor_keymap: EditorKeymap::from_str(editor_keymap.as_str()).unwrap(),
|
||||
editor_soft_wrap: r.get("editor_soft_wrap")?,
|
||||
interface_font_size: r.get("interface_font_size")?,
|
||||
interface_scale: r.get("interface_scale")?,
|
||||
@@ -1043,9 +1091,7 @@ impl<'de> Deserialize<'de> for AnyModel {
|
||||
Some(m) if m == "environment" => {
|
||||
AnyModel::Environment(serde_json::from_value(value).unwrap())
|
||||
}
|
||||
Some(m) if m == "folder" => {
|
||||
AnyModel::Folder(serde_json::from_value(value).unwrap())
|
||||
}
|
||||
Some(m) if m == "folder" => AnyModel::Folder(serde_json::from_value(value).unwrap()),
|
||||
Some(m) if m == "key_value" => {
|
||||
AnyModel::KeyValue(serde_json::from_value(value).unwrap())
|
||||
}
|
||||
@@ -1058,9 +1104,7 @@ impl<'de> Deserialize<'de> for AnyModel {
|
||||
Some(m) if m == "cookie_jar" => {
|
||||
AnyModel::CookieJar(serde_json::from_value(value).unwrap())
|
||||
}
|
||||
Some(m) if m == "plugin" => {
|
||||
AnyModel::Plugin(serde_json::from_value(value).unwrap())
|
||||
}
|
||||
Some(m) if m == "plugin" => AnyModel::Plugin(serde_json::from_value(value).unwrap()),
|
||||
Some(m) => {
|
||||
return Err(serde::de::Error::custom(format!("Unknown model {}", m)));
|
||||
}
|
||||
|
||||
@@ -914,6 +914,7 @@ pub async fn update_settings<R: Runtime>(
|
||||
(SettingsIden::InterfaceFontSize, settings.interface_font_size.into()),
|
||||
(SettingsIden::InterfaceScale, settings.interface_scale.into()),
|
||||
(SettingsIden::EditorFontSize, settings.editor_font_size.into()),
|
||||
(SettingsIden::EditorKeymap, settings.editor_keymap.to_string().into()),
|
||||
(SettingsIden::EditorSoftWrap, settings.editor_soft_wrap.into()),
|
||||
(SettingsIden::Telemetry, settings.telemetry.into()),
|
||||
(SettingsIden::OpenWorkspaceNewWindow, settings.open_workspace_new_window.into()),
|
||||
|
||||
Reference in New Issue
Block a user