From ddd9d8a9b4d43b4b3b833fd6a21ee474eed96ca4 Mon Sep 17 00:00:00 2001 From: TudbuT Date: Wed, 22 May 2024 00:54:28 +0200 Subject: [PATCH] mod 1: send current words to other apps over tcp --- tudbut_mod_1.patch | 192 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 192 insertions(+) create mode 100644 tudbut_mod_1.patch diff --git a/tudbut_mod_1.patch b/tudbut_mod_1.patch new file mode 100644 index 00000000..9d25aa54 --- /dev/null +++ b/tudbut_mod_1.patch @@ -0,0 +1,192 @@ +diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs +index 7be2ea09..3dacb5c8 100644 +--- a/helix-term/src/commands.rs ++++ b/helix-term/src/commands.rs +@@ -3778,6 +3778,10 @@ pub fn insert_char(cx: &mut Context, c: char) { + doc.apply(&t, view.id); + } + ++ // -- TudbuT mod begin ++ helix_view::tt__update_manpage(doc, view.id); ++ // -- TudbuT mod end ++ + helix_event::dispatch(PostInsertChar { c, cx }); + } + +diff --git a/helix-view/src/document.rs b/helix-view/src/document.rs +index 23b597a3..5b4fdc4d 100644 +--- a/helix-view/src/document.rs ++++ b/helix-view/src/document.rs +@@ -1144,6 +1144,9 @@ pub fn set_selection(&mut self, view_id: ViewId, selection: Selection) { + // TODO: use a transaction? + self.selections + .insert(view_id, selection.ensure_invariants(self.text().slice(..))); ++ // -- TudbuT mod begin ++ crate::tt__update_manpage(self, view_id); ++ // -- TudbuT mod end + helix_event::dispatch(SelectionDidChange { + doc: self, + view: view_id, +@@ -1225,6 +1228,9 @@ fn apply_impl( + view_id, + selection.clone().ensure_invariants(self.text.slice(..)), + ); ++ // -- TudbuT mod begin ++ crate::tt__update_manpage(self, view_id); ++ // -- TudbuT mod end + helix_event::dispatch(SelectionDidChange { + doc: self, + view: view_id, +diff --git a/helix-view/src/lib.rs b/helix-view/src/lib.rs +index 14b6e1ce..79541244 100644 +--- a/helix-view/src/lib.rs ++++ b/helix-view/src/lib.rs +@@ -75,3 +75,148 @@ pub fn align_view(doc: &Document, view: &mut View, align: Align) { + use helix_core::char_idx_at_visual_offset; + pub use theme::Theme; + pub use view::View; ++ ++// -- TudbuT mod begin ++ ++/// communicates with the outside world ++#[allow(non_camel_case_types)] ++struct TT__Server { ++ tcp_listener: std::net::TcpListener, ++ tcp_streams: Vec, ++ last_word: String, ++} ++ ++impl TT__Server { ++ fn new() -> Self { ++ // god damn ++ #[derive(Clone)] ++ struct AddrIter + Clone> { ++ inner: T, ++ } ++ impl + Clone> AddrIter { ++ pub fn new(inner: T) -> Self { ++ Self { inner } ++ } ++ } ++ impl + Clone> Iterator for AddrIter { ++ type Item = std::net::SocketAddr; ++ ++ fn next(&mut self) -> Option { ++ Some(std::net::SocketAddr::V4(std::net::SocketAddrV4::new( ++ std::net::Ipv4Addr::new(127, 0, 0, 1), ++ self.inner.next()?, ++ ))) ++ } ++ } ++ impl + Clone> std::net::ToSocketAddrs for AddrIter { ++ type Iter = Self; ++ ++ fn to_socket_addrs(&self) -> std::io::Result { ++ Ok(self.clone()) ++ } ++ } ++ ++ let me = Self { ++ tcp_listener: std::net::TcpListener::bind(AddrIter::new(7400..)).expect("DO NOT REPORT THIS TO HELIX!!! This is a TudbuT mod error: unable to start TT__Server"), ++ tcp_streams: Vec::new(), ++ last_word: String::default(), ++ }; ++ ++ me.tcp_listener.set_nonblocking(true).expect( ++ "DO NOT REPORT THIS TO HELIX!!! This is a TudbuT mod error: unable to set nonblocking", ++ ); ++ ++ me ++ } ++ ++ fn update(&mut self, mut new_word: String) { ++ use std::io::{ErrorKind, Read, Write}; ++ ++ if let Ok((x, _)) = self.tcp_listener.accept() { ++ if x.set_nonblocking(true).is_ok() { ++ self.tcp_streams.push(x); ++ } ++ } ++ new_word += "\n"; ++ if self.last_word != new_word { ++ let b = new_word.as_bytes().len(); ++ let mut buf = [0u8; 1024]; ++ let mut to_remove = Vec::new(); ++ for (i, stream) in self.tcp_streams.iter_mut().enumerate() { ++ match stream.read(&mut buf) { ++ Ok(_n @ 1..) => (), ++ Err(e) if e.kind() == ErrorKind::WouldBlock => (), ++ _ => { ++ to_remove.push(i); ++ continue; ++ } ++ } ++ match stream.write(new_word.as_bytes()) { ++ Ok(n) if n == b => (), ++ _ => to_remove.push(i), ++ } ++ } ++ for i in to_remove { ++ let stream = self.tcp_streams.remove(i); ++ let _ = stream.shutdown(std::net::Shutdown::Both); ++ } ++ ++ self.last_word = new_word; ++ } ++ } ++} ++ ++#[allow(non_upper_case_globals)] ++static TT__SERVER: std::sync::Mutex> = std::sync::Mutex::new(None); ++ ++#[allow(non_snake_case)] ++pub fn tt__update_manpage(doc: &Document, view_id: ViewId) { ++ let c = helix_core::syntax::FileType::Extension("c".to_owned()); ++ ++ fn get_word(text: &str, idx: usize) -> &str { ++ let mut start = idx; ++ let mut end = idx; ++ ++ const WORD_END: &str = " {}()[],#+-/*;<>&!\"'%$?~^|'\n\r"; ++ ++ while start != 0 && !WORD_END.contains(&&text[start - 1..start]) { ++ start = match start.checked_sub(1) { ++ Some(n) => n, ++ None => break, ++ } ++ } ++ ++ while end != text.len() && !WORD_END.contains(&&text[end..=end]) { ++ end += 1; ++ } ++ ++ &text[start..end] ++ } ++ ++ if doc ++ .language ++ .as_ref() ++ .is_some_and(|x| x.file_types.contains(&c)) ++ { ++ let idx = doc.selection(view_id).primary().to() - 1; ++ let lidx = doc.text().char_to_line(idx); ++ let line_idx = doc.text().line_to_char(lidx); ++ let next_line_idx = doc.text().line_to_char(lidx + 1); ++ let idx_in_line = idx - line_idx; ++ ++ let text_in_line = doc.text().slice(line_idx..next_line_idx).to_string(); ++ ++ let word = get_word(&text_in_line, idx_in_line); ++ ++ let mut server = TT__SERVER ++ .lock() ++ .expect("DO NOT REPORT THIS TO HELIX (mod error)"); ++ if let Some(ref mut server) = *server { ++ server.update(word.to_owned()); ++ } else { ++ *server = Some(TT__Server::new()); ++ } ++ } ++} ++ ++// -- TudbuT mod end