Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'src/edi.rs')
| -rw-r--r-- | src/edi.rs | 589 |
1 files changed, 357 insertions, 232 deletions
@@ -1,24 +1,21 @@ use std::collections::HashMap; use std::ffi::OsString; use std::fmt::Debug; -use std::io::BufReader; +use std::io::ErrorKind; use std::mem::take; use std::path::{Path, PathBuf}; -use std::process::Stdio; use std::sync::Arc; use std::time::SystemTime; use Default::default; use ftools::Bind; -use helix_core::syntax::config::FileType; -use log::info; -use lsp_server::Connection; use lsp_types::*; use regex::Regex; use rootcause::report; use ropey::Rope; use rust_fsm::StateMachine; use tokio::sync::oneshot::Sender; +use tree_house::Language; use winit::keyboard::NamedKey; use winit::window::Window; @@ -26,6 +23,7 @@ mod input_handlers; pub use input_handlers::handle2; mod lsp_impl; +pub mod lsp_mn; mod ra; pub mod st; mod wsedit; @@ -35,6 +33,7 @@ use st::*; use crate::bar::Bar; use crate::commands::Cmds; +use crate::edi::lsp_mn::LSPM; use crate::error::WDebug; use crate::gotolist::{At, GoTo}; use crate::hov::{self, HOV_HEIGHT, Hovr, Hovring, Rendered}; @@ -49,8 +48,8 @@ use crate::text::cursor::{Ronge, ceach}; use crate::text::hist::{ClickHistory, Hist}; use crate::text::{LOADER, Mapping, RopeExt, SortTedits, TextArea}; use crate::{ - BoolRequest, CDo, CompletionAction, CompletionState, alt, ctrl, - filter, hash, shift, sym, trm, + BoolRequest, CDo, CompletionAction, CompletionState, Freq, KillRing, + alt, ctrl, filter, hash, shift, sym, }; impl Debug for Editor { @@ -61,13 +60,18 @@ impl Debug for Editor { .field("origin", &self.origin) .field("state", &self.state.name()) .field("bar", &self.bar) - .field("workspace", &self.workspace) .field("hist", &self.hist) .field("mtime", &self.mtime) .finish() } } - +#[derive( + Default, serde_derive::Serialize, serde_derive::Deserialize, Debug, +)] +pub struct Edithin { + pub files: HashMap<PathBuf, Edithin>, + pub mtime: Option<std::time::SystemTime>, +} #[derive(Default, serde_derive::Serialize, serde_derive::Deserialize)] pub struct Editor { pub files: HashMap<PathBuf, Editor>, @@ -77,14 +81,11 @@ pub struct Editor { pub state: State, #[serde(skip)] pub bar: Bar, - pub workspace: Option<PathBuf>, + // pub workspace: Option<PathBuf>, + #[serde(skip)] pub git_dir: Option<PathBuf>, #[serde(skip)] - pub lsp: Option<( - &'static Client, - std::thread::JoinHandle<()>, - Option<Sender<Arc<dyn Window>>>, - )>, + pub lsp: Option<(Arc<Client>, Option<Sender<Arc<dyn Window>>>)>, // #[serde(skip)] pub requests: Requests, #[serde(skip)] @@ -98,9 +99,13 @@ pub struct Editor { // pub git_diff: // Option<std::rc::Rc<std::cell::RefCell<imara_diff::Diff>>>, } + macro_rules! lsp { + (&$self:ident) => { + $self.lsp.as_ref().map(|(x,..)| x) + }; ($self:ident) => { - $self.lsp.as_ref().map(|(x, ..)| *x) + $self.lsp.as_ref().map(|(x, ..)| x.clone()) }; ($self:ident + p) => { $crate::edi::lsp!($self).zip($self.origin.as_deref()) @@ -112,6 +117,13 @@ macro_rules! lsp { return $($else)?; }; }; + (let $lsp:ident = $self:ident $(else $else:expr)?) => { + let Some($lsp) = + $crate::edi::lsp!($self) + else { + return $($else)?; + }; + }; } pub(crate) use lsp; macro_rules! inlay { @@ -171,170 +183,237 @@ macro_rules! change { } pub(crate) use change; -fn rooter( +fn rooter_( x: &Path, mut search: impl FnMut(OsString) -> bool + Clone, -) -> Option<PathBuf> { - for f in std::fs::read_dir(&x).ok()?.filter_map(Result::ok) { + whilst: impl for<'a> FnMut(&&'a Path) -> bool + Clone, + found: &mut Vec<PathBuf>, +) { + let Some(d) = std::fs::read_dir(&x).ok() else { return }; + for f in d.filter_map(Result::ok) { if search(f.file_name()) { - return Some(f.path().with_file_name("").to_path_buf()); + found.push(f.path().with_file_name("").to_path_buf()); } } - x.parent().and_then(rooter.rbind(search)) + x.parent() + .filter(whilst.clone()) + .map(|x| rooter_(x, search, whilst, found)); } -impl Editor { - pub fn new() -> rootcause::Result<Self> { - let mut me = Self::default(); +fn rooter( + x: &Path, + search: impl FnMut(OsString) -> bool + Clone, - let o = std::env::args() + whilst: impl for<'a> FnMut(&&'a Path) -> bool + Clone, +) -> Option<PathBuf> { + let mut v = vec![]; + rooter_(x, search, whilst, &mut v); + v.try_remove(v.len().checked_sub(1)?) +} + +impl Editor { + pub fn new( + lsp_mn: &mut LSPM, + ) -> rootcause::Result<(Self, Freq, KillRing)> { + let mut o = std::env::args() .nth(1) .and_then(|x| PathBuf::try_from(x).ok()) - .and_then(|x| x.canonicalize().ok()); + .and_then(|x| { + x.canonicalize() + .inspect_err(|_| { + _ = std::fs::File::create(&x); + }) + .ok() + .or_else(|| x.canonicalize().ok()) + .or(Some(x)) + }) + .or_else(|| { + rfd::FileDialog::new() + .set_can_create_directories(true) + .set_title("pick dir to open") + .pick_folder() + }); + if let Some(x) = &o { + match std::fs::read_to_string(x) + .map(|x| x.replace("\r\n", "\n")) + { + Ok(_) => {} + Err(e) + if e.kind() == ErrorKind::IsADirectory + && let h = hash(&x) + && let cf = cfgdir().join(format!("{h:x}")) + && let at = cf.join(SSTORE) + && at.exists() => + { + let x = std::fs::read(at)?; + let x = bendncode::from_bytes::<Edithin>(&x)?; + o = Some( + x.files + .iter() + .max_by_key(|(_, x)| x.mtime) + .map(ttools::fst) + .expect("file") + .clone(), + ); + } + Err(e) if e.kind() == ErrorKind::IsADirectory => + o = rfd::FileDialog::new() + .set_directory(x) + .set_can_create_directories(true) + .set_title("pick file in project to open") + .pick_file(), + Err(e) => { + eprintln!("path could not be opened: {e}"); + std::process::exit(5); + } + } + }; + Editor::new_for(o, lsp_mn) + } - if let Some(x) = std::env::args().nth(1) { - me.text.insert(&std::fs::read_to_string(x)?); + pub fn upto(&self) -> impl std::ops::Fn(&&Path) -> bool + Clone { + let upto = self + .git_dir + .clone() + .or(std::env::current_dir().ok()) + .unwrap_or(PathBuf::from("/home/")); + move |x: &&Path| x.starts_with(&upto) + } + + pub fn root_for(&self, o: &Path, l: Language) -> Option<PathBuf> { + let l = LOADER.language(l).config(); + + o.parent() + .and_then(|x| rooter(&x, |f| l.roots.is_match(f), self.upto())) + .or(std::env::current_dir().ok()) + .and_then(|x| x.canonicalize().ok()) + } + pub fn vsc(&self) -> Option<serde_json::Value> { + self.origin + .as_ref() + .and_then(|x| x.parent()) + .and_then(|x| rooter(&x, |x| x == ".vscode", self.upto())) + .map(|x| (x.clone(), x.join(".vscode").join("settings.json"))) + .filter(|x| x.1.exists()) + .and_then(|(ws, x)| vsc_settings::load(&x, &ws).ok()) + } + pub fn load_lsp(&mut self, lsp_mn: &mut LSPM) { + self.language = self + .origin + .as_deref() + .and_then(|o| LOADER.language_for_filename(o)); + let ws = self + .origin + .as_deref() + .zip(self.language) + .and_then(|(p, l)| self.root_for(p, l)); + let l = ws + .as_ref() + .zip(self.language) + .and_then(|(w, ln)| lsp_mn.load(w, ln, self.vsc())); + self.lsp = l; + } + pub fn new_for( + o: Option<PathBuf>, + lsp_mn: &mut LSPM, + ) -> rootcause::Result<(Self, Freq, KillRing)> { + let mut me = Self::default(); + if let Some(o) = o.as_deref() + && let o = std::fs::read_to_string(o) + .map(|x| x.replace("\r\n", "\n")) + .unwrap() + { + me.text.insert(&o); me.text.cursor = default(); - }; + } let n = o.as_deref().and_then(|o| LOADER.language_for_filename(o)); me.language = n; - let l = - n.map(|n| LOADER.languages().nth(n.idx()).unwrap().1.config()); - me.workspace = o - .as_ref() - .and_then(|x| x.parent()) + let l = n.map(|n| LOADER.language(n).config()); + me.git_dir = o + .as_deref() .and_then(|x| { - l.and_then(|l| rooter(&x, |f| l.roots.is_match(f))) + x.ancestors() + .find(|x| x.join(".git").exists()) + .map(PathBuf::from) }) - .or(std::env::current_dir().ok()) .and_then(|x| x.canonicalize().ok()); - let vsc = o - .as_ref() - .and_then(|x| x.parent()) - .and_then(|x| rooter(&x, |x| x == ".vscode")) - .map(|x| (x.clone(), x.join(".vscode").join("settings.json"))) - .filter(|x| x.1.exists()) - .and_then(|(ws, x)| (vsc_settings::load(&x, &ws)).ok()); + let ws = o.as_deref().zip(n).and_then(|(p, l)| me.root_for(p, l)); let mut loaded_state = false; - if let Some(ws) = me.workspace.as_deref() + let mut freq = default(); + let mut kr = default(); + if let Some(ws) = ws.as_deref() && let h = hash(&ws) - && let at = cfgdir().join(format!("{h:x}")).join(STORE) + && let cf = cfgdir().join(format!("{h:x}")) + && let at = cf.join(SSTORE) && at.exists() { + println!("loaded "); let x = std::fs::read(at)?; - let x = bendy::serde::from_bytes::<Editor>(&x)?; + let x = bendncode::from_bytes::<Editor>(&x)?; + let gd = me.git_dir.take(); me = x; + me.git_dir = gd; loaded_state = true; - assert!(me.workspace.is_some()); + // assert!(me.workspace.is_some()); + if let at = cf.join(FSTORE) + && at.exists() + { + let x = std::fs::read(at)?; + freq = bendncode::from_bytes::<Freq>(&x)?; + } + if let at = cf.join(KSTORE) + && at.exists() + { + let x = std::fs::read(at)?; + kr = bendncode::from_bytes::<KillRing>(&x)?; + } } + println!("set git dir {:?}", &me.git_dir); me.language = n; - me.git_dir = me - .workspace - .as_deref() - .and_then(|x| rooter(&x, |x| x == ".git")) - .and_then(|x| x.canonicalize().ok()); me.origin = o; - me.tree = me.workspace.as_ref().map(|x| { - walkdir::WalkDir::new(x) - .into_iter() - .flatten() - .filter(|x| { - let x = x.path(); - l.is_some_and(|l| { - l.file_types.iter().any(|y| match y { - FileType::Extension(e) => - x.extension().is_some_and(|x| x == &**e), - FileType::Glob(glob) => - glob.compile_matcher().is_match(x), - }) - }) - }) - .map(|x| x.path().to_owned()) - .collect::<Vec<_>>() - }); - let l = me.workspace.as_ref().zip(l).map(|(workspace, l)| { - let (Connection { sender, receiver }, conf) = if l.language_id - == "rust" - { - super let (_jh, a) = ra::ra(workspace.clone()); - ( - a, - ( - &LOADER.language_server_configs()["rust-analyzer"], - &l.language_servers[0], - ), - ) - } else { - let (mut c, conf) = l - .language_servers - .iter() - .find_map(|l| { - let lc = LOADER - .language_server_configs() - .get(&l.name)?; - std::process::Command::new(&lc.command) - .args(&lc.args) - .stdin(Stdio::piped()) - .stdout(Stdio::piped()) - .stderr(Stdio::inherit()) - .spawn() - .ok() - .zip(Some((lc, l))) - }) - .ok_or(report!( - "no lsp for this language; install one of {:?}", - l.language_servers - )) - .unwrap(); - super let (x, _iot) = - Connection::stdio( - BufReader::new(c.stdout.take().unwrap()), - c.stdin.take().unwrap(), - ); - (x, conf) - }; - info!("spawned {conf:?}"); - let (c, t2, changed) = crate::lsp::run( - (sender, receiver), - WorkspaceFolder { - uri: Url::from_file_path(&workspace).unwrap(), - name: workspace - .file_name() - .unwrap() - .to_string_lossy() - .into_owned(), - }, - vsc, - conf, - ) - .unwrap(); - (&*Box::leak(Box::new(c)), (t2), Some(changed)) - }); + // me.tree = ws.as_ref().map(|x| { + // walkdir::WalkDir::new(x) + // .into_iter() + // .flatten() + // .filter(|x| { + // let x = x.path(); + // l.is_some_and(|l| { + // l.file_types.iter().any(|y| match y { + // FileType::Extension(e) => + // x.extension().is_some_and(|x| x == &**e), + // FileType::Glob(glob) => + // glob.compile_matcher().is_match(x), + // }) + // }) + // }) + // .map(|x| x.path().to_owned()) + // .collect::<Vec<_>>() + // }); + let g = me.git_dir.clone(); if let Some(o) = me.origin.clone() && loaded_state { - let w = me.workspace.clone(); - let la = me.language; - let t = me.tree.clone(); - assert!(me.files.len() != 0); - me.open_or_restore(&o, l, la, None, w)?; - me.git_dir = g; - me.tree = t; + if me.files.len() != 0 { + log::error!( + "too many files? {:?}", + me.files.keys().collect::<Vec<_>>() + ); + } + me.open_or_restore(&o, g, None, lsp_mn)?; me.language = n; } else { - me.lsp = l; + me.load_lsp(lsp_mn); me.hist.lc = me.text.cursor.clone(); me.hist.last = me.text.changes.clone(); - if let Some(((c, ..), origin)) = - me.lsp.as_ref().zip(me.origin.as_deref()) - { + if let Some((c, origin)) = lsp!(me + p) { c.open( &origin, - std::fs::read_to_string(&origin)?, + std::fs::read_to_string(&origin) + .map(|x| x.replace("\r\n", "\n"))?, me.language.unwrap(), )?; c.rq_semantic_tokens( @@ -345,7 +424,7 @@ impl Editor { } me.git_dir = g; me.mtime = Self::modify(me.origin.as_deref()); - + me.tree(); // me.hist.last = me.text.clone(); // me.lsp.as_ref().zip(me.origin.as_deref()).map( // |((x, ..), origin)| { @@ -358,7 +437,7 @@ impl Editor { // }, // ); } - Ok(me) + Ok((me, freq, kr)) } #[must_use = "please apply this"] @@ -385,7 +464,8 @@ impl Editor { self.bar.last_action = "saved".into(); lsp!(self + p).map(|(l, o)| { if let Ok(fut) = l.format(o) - && let Ok(Some(v)) = l.runtime.block_on(fut) + && let Ok(Ok(Some(v))) = + l.by(fut, tokio::time::Duration::from_millis(500)) && let Err(x) = self.text.apply_tedits_adjusting(&mut { v }) { @@ -472,6 +552,30 @@ impl Editor { inlay!(self); } + pub fn paste_m<T: AsRef<str>>( + &mut self, + r: impl Iterator<Item = T> + DoubleEndedIterator + ExactSizeIterator, + ) { + // let bounds = unsafe { &*META.splits }; + // let pieces = bounds.windows(2).map(|w| unsafe { + // std::str::from_utf8_unchecked(&r.as_bytes()[w[0]..w[1]]) + // }); + if r.len() == self.text.cursor.iter().len() { + for (piece, cursor) in + r.rev().zip(0..self.text.cursor.iter().count()) + { + let c = self.text.cursor.iter().nth(cursor).unwrap(); + self.text.insert_at(*c, piece.as_ref()).unwrap(); + } + } else { + let new = r + .fold(String::default(), |acc, x| acc + x.as_ref() + "\n"); + + // vscode behaviour: insane? + self.text.insert(&new); + eprintln!("hrmst"); + } + } pub fn paste(&mut self) { self.hist.push_if_changed(&mut self.text); let r = clipp::paste(); @@ -480,19 +584,7 @@ impl Editor { let pieces = bounds.windows(2).map(|w| unsafe { std::str::from_utf8_unchecked(&r.as_bytes()[w[0]..w[1]]) }); - if unsafe { META.count } == self.text.cursor.iter().len() { - for (piece, cursor) in - pieces.zip(0..self.text.cursor.iter().count()) - { - let c = self.text.cursor.iter().nth(cursor).unwrap(); - self.text.insert_at(*c, piece).unwrap(); - } - } else { - let new = pieces.intersperse("\n").collect::<String>(); - // vscode behaviour: insane? - self.text.insert(&new); - eprintln!("hrmst"); - } + self.paste_m(pieces); } else { self.text.insert(&clipp::paste()); } @@ -504,6 +596,7 @@ impl Editor { &mut self, x: &Path, w: Arc<dyn Window>, + lsp_mn: &mut LSPM, ) -> rootcause::Result<()> { let x = x.canonicalize()?.to_path_buf(); if Some(&*x) == self.origin.as_deref() { @@ -511,91 +604,99 @@ impl Editor { return Ok(()); } let r = self.text.r; - let ws = self.workspace.clone(); - let git_dir = self.workspace.clone(); - let tree = self.tree.clone(); - let lsp = self.lsp.take(); - let l = self.language; + // let ws = self.workspace.clone(); + let git_dir = self.git_dir.clone(); + // let lsp = self.lsp.take(); let mut me = take(self); let f = take(&mut me.files); if let Some(x) = me.origin.clone() { - lsp.as_ref().map(|l| l.0.close(&x)); + lsp!(me).as_ref().map(|l| l.close(&x)); self.files.insert(x, me); self.files.extend(f); // assert!(f.len() == 0); } - self.open_or_restore(&x, lsp, l, Some(w), ws)?; + self.open_or_restore(&x, git_dir, Some(w), lsp_mn)?; self.text.r = r; - self.tree = tree; - self.git_dir = git_dir; // maybe it should change? you know. sometimes? Ok(()) } + fn restore( + &mut self, + git_dir: Option<PathBuf>, + // lsp: Option<(Arc<Client>, Option<Sender<Arc<dyn Window>>>)>, + // l: Option<helix_core::Language>, + with: Editor, + lsp_mn: &mut LSPM, + ) -> rootcause::Result<()> { + let f = take(&mut self.files); + + *self = with; + assert!(self.files.len() == 0); + self.files = f; + self.bar.last_action = "restored".into(); + if self.mtime != Self::modify(self.origin.as_deref()) { + self.hist.push_if_changed(&mut self.text); + self.text.rope = Rope::from_str( + &std::fs::read_to_string( + self.origin + .as_ref() + .ok_or(report!("origin missing"))?, + ) + .map(|x| x.replace("\r\n", "\n")) + .unwrap(), + ); + + self.text.cursor.first_mut().position = self + .text + .cursor + .first() + .position + .min(self.text.rope.len_chars()); + self.mtime = Self::modify(self.origin.as_deref()); + self.bar.last_action = "restored -> reloaded".into(); + take(&mut self.requests); + self.hist.push(&mut self.text) + } + self.git_dir = git_dir; + self.load_lsp(lsp_mn); + + if let Some((x, origin)) = lsp!(self + p) { + x.open( + &origin, + self.text.rope.to_string(), + self.language.unwrap(), + )?; + } + Ok(()) + } fn open_or_restore( &mut self, x: &Path, - lsp: Option<( - &'static Client, - std::thread::JoinHandle<()>, - Option<Sender<Arc<dyn Window>>>, - )>, - l: Option<helix_core::Language>, + git_dir: Option<PathBuf>, + // lsp: Option<(Arc<Client>, Option<Sender<Arc<dyn Window>>>)>, + // l: Option<helix_core::Language>, w: Option<Arc<dyn Window>>, - ws: Option<PathBuf>, + lsp_mn: &mut LSPM, + // ws: Option<PathBuf>, ) -> rootcause::Result<()> { if let Some(x) = self.files.remove(x) { - let f = take(&mut self.files); - - *self = x; - assert!(self.files.len() == 0); - self.files = f; - self.bar.last_action = "restored".into(); - if self.mtime != Self::modify(self.origin.as_deref()) { - self.hist.push_if_changed(&mut self.text); - self.text.rope = Rope::from_str( - &std::fs::read_to_string( - self.origin - .as_ref() - .ok_or(report!("origin missing"))?, - ) - .unwrap(), - ); - - self.text.cursor.first_mut().position = self - .text - .cursor - .first() - .position - .min(self.text.rope.len_chars()); - self.mtime = Self::modify(self.origin.as_deref()); - self.bar.last_action = "restored -> reloaded".into(); - take(&mut self.requests); - self.hist.push(&mut self.text) - } - self.lsp = lsp; - self.language = l; - if let Some((x, origin)) = lsp!(self + p) { - x.open( - &origin, - self.text.rope.to_string(), - self.language.unwrap(), - )?; - } + self.restore(git_dir, x, lsp_mn)? } else { - self.workspace = ws; + // self.workspace = ws; self.origin = Some(x.to_path_buf()); - let new = std::fs::read_to_string(&x)?; + let new = std::fs::read_to_string(&x) + .map(|x| x.replace("\r\n", "\n"))?; take(&mut self.text); self.text.insert(&new); take(&mut self.text.changes); self.text.cursor.just(0, &self.text.rope); self.bar.last_action = "open".into(); self.mtime = Self::modify(self.origin.as_deref()); - self.lsp = lsp; - self.language = l; + self.git_dir = git_dir; + self.load_lsp(lsp_mn); if let Some((ls, origin)) = lsp!(self + p) { take(&mut self.requests); @@ -607,9 +708,30 @@ impl Editor { .peel()?; } } + + self.tree(); self.set_title(w); Ok(()) } + pub fn tree(&mut self) { + fn is_hidden(entry: &walkdir::DirEntry) -> bool { + entry + .file_name() + .to_str() + .map(|s| s.starts_with(".")) + .unwrap_or(false) + } + self.tree = self.git_dir.as_ref().map(|x| { + walkdir::WalkDir::new(x) + .into_iter() + .filter_entry(|e| !is_hidden(e)) + .flatten() + .filter(|x| !x.path().starts_with(".")) + .filter(|x| !x.path().is_dir()) + .map(|x| x.path().to_owned()) + .collect::<Vec<_>>() + }); + } pub fn set_title(&self, w: Option<Arc<dyn Window>>) { if let Some(x) = w && let Some(t) = self.title() @@ -618,22 +740,26 @@ impl Editor { } } pub fn title(&self) -> Option<String> { - [self.workspace.as_deref(), self.origin.as_deref()] + [self.git_dir.as_deref(), self.origin.as_deref()] .try_map(|x| { x.and_then(Path::file_name).and_then(|x| x.to_str()) }) .map(|[wo, or]| format!("gracilaria - {wo} - {or}")) } - pub fn store(&mut self) -> rootcause::Result<()> { - let ws = self.workspace.clone(); + pub fn store( + &mut self, + fq: &Freq, + kr: &KillRing, + ) -> rootcause::Result<()> { + // let ws = self.workspace.clone(); let tree = self.tree.clone(); let mtime = self.mtime.clone(); let origin = self.origin.clone(); - if let Some(w) = self.workspace.clone() { + if let Some(w) = self.git_dir.clone() { let mut me = take(self); - self.workspace = ws; + // self.workspace = ws; self.tree = tree; self.mtime = mtime; self.origin = origin; @@ -647,9 +773,13 @@ impl Editor { let cfgdir = cfgdir(); let p = cfgdir.join(format!("{hash:x}")); std::fs::create_dir_all(&p)?; - let b = bendy::serde::to_bytes(&self).unwrap(); - bendy::serde::from_bytes::<Editor>(&b)?; - std::fs::write(p.join(STORE), &b)?; + let b = bendncode::to_bytes(&self)?; + bendncode::from_bytes::<Editor>(&b)?; + std::fs::write(p.join(SSTORE), &b)?; + let b = bendncode::to_bytes(fq)?; + std::fs::write(p.join(FSTORE), &b)?; + let b = bendncode::to_bytes(kr)?; + std::fs::write(p.join(KSTORE), &b)?; } Ok(()) } @@ -658,10 +788,11 @@ impl Editor { &mut self, g: impl Into<GoTo<'_>>, w: Arc<dyn Window>, + lsp_mn: &mut LSPM, ) -> rootcause::Result<()> { let g = g.into(); let f = g.path.canonicalize()?; - self.open(&f, w.clone())?; + self.open(&f, w.clone(), lsp_mn)?; match g.at { At::R(r) => { @@ -697,17 +828,11 @@ fn cfgdir() -> PathBuf { std::env::var("HOME") .map(PathBuf::from) .map(|x| x.join(".config")) + .or(std::env::var("AppData").map(PathBuf::from)) }) .unwrap_or("/tmp/".into()) .join("gracilaria") } -const STORE: &str = "state.torrent"; -#[track_caller] -#[allow(dead_code)] -fn rtt<T: serde::Serialize + serde::Deserialize<'static>>( - x: &T, -) -> Result<T, bendy::serde::Error> { - bendy::serde::from_bytes::<T>( - bendy::serde::to_bytes(x).unwrap().leak(), - ) -} +const SSTORE: &str = "state.bendn"; +const FSTORE: &str = "freq.bendn"; +const KSTORE: &str = "killring.bendn"; |