Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'src/edi.rs')
-rw-r--r--src/edi.rs589
1 files changed, 357 insertions, 232 deletions
diff --git a/src/edi.rs b/src/edi.rs
index d648885..9d01fb8 100644
--- a/src/edi.rs
+++ b/src/edi.rs
@@ -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";