Skip to main content
Glama

Edit-MCP

state.rs7.8 kB
// Copyright (c) Microsoft Corporation. // Licensed under the MIT License. use std::borrow::Cow; use std::ffi::{OsStr, OsString}; use std::mem; use std::path::{Path, PathBuf}; use edit::framebuffer::IndexedColor; use edit::helpers::*; use edit::tui::*; use edit::{apperr, buffer, icu, sys}; use crate::documents::DocumentManager; use crate::localization::*; #[repr(transparent)] pub struct FormatApperr(apperr::Error); impl From<apperr::Error> for FormatApperr { fn from(err: apperr::Error) -> Self { Self(err) } } impl std::fmt::Display for FormatApperr { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self.0 { apperr::APP_ICU_MISSING => f.write_str(loc(LocId::ErrorIcuMissing)), apperr::Error::App(code) => write!(f, "Unknown app error code: {code}"), apperr::Error::Icu(code) => icu::apperr_format(f, code), apperr::Error::Sys(code) => sys::apperr_format(f, code), } } } pub struct DisplayablePathBuf { value: PathBuf, str: Cow<'static, str>, } impl DisplayablePathBuf { #[allow(dead_code, reason = "only used on Windows")] pub fn from_string(string: String) -> Self { let str = Cow::Borrowed(string.as_str()); let str = unsafe { mem::transmute::<Cow<'_, str>, Cow<'_, str>>(str) }; let value = PathBuf::from(string); Self { value, str } } pub fn from_path(value: PathBuf) -> Self { let str = value.to_string_lossy(); let str = unsafe { mem::transmute::<Cow<'_, str>, Cow<'_, str>>(str) }; Self { value, str } } pub fn as_path(&self) -> &Path { &self.value } pub fn as_str(&self) -> &str { &self.str } pub fn as_bytes(&self) -> &[u8] { self.value.as_os_str().as_encoded_bytes() } } impl Default for DisplayablePathBuf { fn default() -> Self { Self { value: Default::default(), str: Cow::Borrowed("") } } } impl Clone for DisplayablePathBuf { fn clone(&self) -> Self { Self::from_path(self.value.clone()) } } impl From<OsString> for DisplayablePathBuf { fn from(s: OsString) -> Self { Self::from_path(PathBuf::from(s)) } } impl<T: ?Sized + AsRef<OsStr>> From<&T> for DisplayablePathBuf { fn from(s: &T) -> Self { Self::from_path(PathBuf::from(s)) } } pub struct StateSearch { pub kind: StateSearchKind, pub focus: bool, } #[derive(Clone, Copy, PartialEq, Eq)] pub enum StateSearchKind { Hidden, Disabled, Search, Replace, } #[derive(Clone, Copy, PartialEq, Eq)] pub enum StateFilePicker { None, Open, SaveAs, SaveAsShown, // Transitioned from SaveAs } #[derive(Clone, Copy, PartialEq, Eq)] pub enum StateEncodingChange { None, Convert, Reopen, } pub struct State { pub menubar_color_bg: u32, pub menubar_color_fg: u32, pub documents: DocumentManager, // A ring buffer of the last 10 errors. pub error_log: [String; 10], pub error_log_index: usize, pub error_log_count: usize, pub wants_file_picker: StateFilePicker, pub file_picker_pending_dir: DisplayablePathBuf, pub file_picker_pending_dir_revision: u64, // Bumped every time `file_picker_pending_dir` changes. pub file_picker_pending_name: PathBuf, pub file_picker_entries: Option<Vec<DisplayablePathBuf>>, pub file_picker_overwrite_warning: Option<PathBuf>, // The path the warning is about. pub wants_search: StateSearch, pub search_needle: String, pub search_replacement: String, pub search_options: buffer::SearchOptions, pub search_success: bool, pub wants_encoding_picker: bool, pub encoding_picker_needle: String, pub encoding_picker_results: Option<Vec<icu::Encoding>>, pub wants_save: bool, pub wants_statusbar_focus: bool, pub wants_encoding_change: StateEncodingChange, pub wants_indentation_picker: bool, pub wants_document_picker: bool, pub wants_about: bool, pub wants_close: bool, pub wants_exit: bool, pub wants_goto: bool, pub goto_target: String, pub goto_invalid: bool, pub osc_title_filename: String, pub osc_clipboard_seen_generation: u32, pub osc_clipboard_send_generation: u32, pub osc_clipboard_always_send: bool, pub exit: bool, } impl State { pub fn new() -> apperr::Result<Self> { Ok(Self { menubar_color_bg: 0, menubar_color_fg: 0, documents: Default::default(), error_log: [const { String::new() }; 10], error_log_index: 0, error_log_count: 0, wants_file_picker: StateFilePicker::None, file_picker_pending_dir: Default::default(), file_picker_pending_dir_revision: 0, file_picker_pending_name: Default::default(), file_picker_entries: None, file_picker_overwrite_warning: None, wants_search: StateSearch { kind: StateSearchKind::Hidden, focus: false }, search_needle: Default::default(), search_replacement: Default::default(), search_options: Default::default(), search_success: true, wants_encoding_picker: false, encoding_picker_needle: Default::default(), encoding_picker_results: Default::default(), wants_save: false, wants_statusbar_focus: false, wants_encoding_change: StateEncodingChange::None, wants_indentation_picker: false, wants_document_picker: false, wants_about: false, wants_close: false, wants_exit: false, wants_goto: false, goto_target: Default::default(), goto_invalid: false, osc_title_filename: Default::default(), osc_clipboard_seen_generation: 0, osc_clipboard_send_generation: 0, osc_clipboard_always_send: false, exit: false, }) } } pub fn draw_add_untitled_document(ctx: &mut Context, state: &mut State) { if let Err(err) = state.documents.add_untitled() { error_log_add(ctx, state, err); } } pub fn error_log_add(ctx: &mut Context, state: &mut State, err: apperr::Error) { let msg = format!("{}", FormatApperr::from(err)); if !msg.is_empty() { state.error_log[state.error_log_index] = msg; state.error_log_index = (state.error_log_index + 1) % state.error_log.len(); state.error_log_count = state.error_log.len().min(state.error_log_count + 1); ctx.needs_rerender(); } } pub fn draw_error_log(ctx: &mut Context, state: &mut State) { ctx.modal_begin("error", loc(LocId::ErrorDialogTitle)); ctx.attr_background_rgba(ctx.indexed(IndexedColor::Red)); ctx.attr_foreground_rgba(ctx.indexed(IndexedColor::BrightWhite)); { ctx.block_begin("content"); ctx.attr_padding(Rect::three(0, 2, 1)); { let off = state.error_log_index + state.error_log.len() - state.error_log_count; for i in 0..state.error_log_count { let idx = (off + i) % state.error_log.len(); let msg = &state.error_log[idx][..]; if !msg.is_empty() { ctx.next_block_id_mixin(i as u64); ctx.label("error", msg); ctx.attr_overflow(Overflow::TruncateTail); } } } ctx.block_end(); if ctx.button("ok", loc(LocId::Ok), ButtonStyle::default()) { state.error_log_count = 0; } ctx.attr_position(Position::Center); ctx.inherit_focus(); } if ctx.modal_end() { state.error_log_count = 0; } }

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/mixelpixx/microsoft-edit-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server