From 996ced4bec99a0b627dd5aa39a15608eb8d3200c Mon Sep 17 00:00:00 2001 From: daa Date: Mon, 9 Apr 2018 23:11:15 +0300 Subject: [PATCH] Read from stdin #87 --- Cargo.lock | 1 + Cargo.toml | 2 ++ src/main.rs | 36 +++++++++++++++++++++++++++++++----- src/nvim/mod.rs | 16 ++++++++++++++++ src/shell.rs | 28 +++++++++++++++++++++++++--- 5 files changed, 75 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6dc093f..4ef92b1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -379,6 +379,7 @@ dependencies = [ "gtk-sys 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "htmlescape 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "neovim-lib 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "pango 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/Cargo.toml b/Cargo.toml index 463b2bc..787059f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -43,6 +43,8 @@ serde_derive = "1.0" toml = "0.4" serde_json = "1.0" +libc = "0.2" + #[dependencies.neovim-lib] #git = "https://github.com/daa84/neovim-lib" diff --git a/src/main.rs b/src/main.rs index 265e702..84f6836 100644 --- a/src/main.rs +++ b/src/main.rs @@ -23,11 +23,12 @@ extern crate pango_sys; extern crate pangocairo; extern crate percent_encoding; extern crate phf; -extern crate rmpv; extern crate regex; -extern crate unicode_width; +extern crate rmpv; extern crate unicode_segmentation; +extern crate unicode_width; +extern crate libc; extern crate serde; #[macro_use] extern crate serde_derive; @@ -63,6 +64,8 @@ mod subscriptions; mod misc; use std::env; +use std::io::Read; +use std::cell::RefCell; use std::time::Duration; use std::str::FromStr; use gio::prelude::*; @@ -78,6 +81,8 @@ const DISABLE_WIN_STATE_RESTORE: &str = "--disable-win-restore"; fn main() { env_logger::init(); + let input_data = RefCell::new(read_piped_input()); + let app_flags = gio::ApplicationFlags::HANDLES_OPEN | gio::ApplicationFlags::NON_UNIQUE; glib::set_program_name(Some("NeovimGtk")); @@ -88,12 +93,14 @@ fn main() { gtk::Application::new(Some("org.daa.NeovimGtk"), app_flags) }.expect("Failed to initialize GTK application"); - app.connect_activate(activate); + app.connect_activate(move |app| { + activate(app, input_data.replace(None)) + }); app.connect_open(open); let new_window_action = gio::SimpleAction::new("new-window", None); let app_ref = app.clone(); - new_window_action.connect_activate(move |_, _| activate(&app_ref)); + new_window_action.connect_activate(move |_, _| activate(&app_ref, None)); app.add_action(&new_window_action); gtk::Window::set_default_icon_name("org.daa.NeovimGtk"); @@ -117,16 +124,18 @@ fn open(app: >k::Application, files: &[gio::File], _: &str) { nvim_bin_path(std::env::args()), files_list, nvim_timeout(std::env::args()), + None, )); ui.init(app, !nvim_disable_win_state(std::env::args())); } -fn activate(app: >k::Application) { +fn activate(app: >k::Application, input_data: Option) { let mut ui = Ui::new(ShellOptions::new( nvim_bin_path(std::env::args()), Vec::new(), nvim_timeout(std::env::args()), + input_data, )); ui.init(app, !nvim_disable_win_state(std::env::args())); @@ -165,6 +174,23 @@ where .unwrap_or(false) } +fn read_piped_input() -> Option { + let isatty = unsafe { libc::isatty(libc::STDIN_FILENO) != 0 }; + + if !isatty { + let mut buf = String::new(); + match std::io::stdin().read_to_string(&mut buf) { + Ok(_) => Some(buf), + Err(err) => { + error!("Error read stdin {}", err); + None + } + } + } else { + None + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/src/nvim/mod.rs b/src/nvim/mod.rs index bda9ae0..898f6da 100644 --- a/src/nvim/mod.rs +++ b/src/nvim/mod.rs @@ -141,6 +141,7 @@ pub fn post_start_init( open_paths: Vec, cols: u64, rows: u64, + input_data: Option, ) -> result::Result<(), NvimInitError> { nvim.borrow() .unwrap() @@ -170,6 +171,21 @@ pub fn post_start_init( .command_async(&command) .cb(|r| r.report_err()) .call(); + } else { + if let Some(input_data) = input_data { + let mut nvim = nvim.borrow().unwrap(); + let buf = nvim.get_current_buf().ok_and_report(); + + if let Some(buf) = buf { + buf.set_lines( + &mut *nvim, + 0, + 0, + true, + input_data.lines().map(|l| l.to_owned()).collect(), + ).report_err(); + } + } } Ok(()) diff --git a/src/shell.rs b/src/shell.rs index 0c16053..b8a2eba 100644 --- a/src/shell.rs +++ b/src/shell.rs @@ -495,6 +495,7 @@ pub struct ShellOptions { nvim_bin_path: Option, open_paths: Vec, timeout: Option, + input_data: Option, } impl ShellOptions { @@ -502,13 +503,25 @@ impl ShellOptions { nvim_bin_path: Option, open_paths: Vec, timeout: Option, + input_data: Option, ) -> Self { ShellOptions { nvim_bin_path, open_paths, timeout, + input_data, } } + + // remove input data from original + // shell option, as it need to be used only once + pub fn take(&mut self) -> Self { + let input_data = self.input_data.take(); + let mut clone = self.clone(); + clone.input_data = input_data; + + clone + } } pub struct Shell { @@ -1044,7 +1057,13 @@ fn init_nvim_async( }); // attach ui - if let Err(err) = nvim::post_start_init(nvim, options.open_paths, cols as u64, rows as u64) { + if let Err(err) = nvim::post_start_init( + nvim, + options.open_paths, + cols as u64, + rows as u64, + options.input_data, + ) { show_nvim_init_error(&err, state_arc.clone()); } else { set_nvim_initialized(state_arc); @@ -1142,7 +1161,7 @@ fn init_nvim(state_ref: &Arc>) { let state_arc = state_ref.clone(); let nvim_handler = NvimHandler::new(state_ref.clone()); - let options = state.options.clone(); + let options = state.options.take(); thread::spawn(move || init_nvim_async(state_arc, nvim_handler, options, cols, rows)); } } @@ -1157,7 +1176,10 @@ impl State { pub fn on_put(&mut self, text: String) -> RepaintMode { let double_width = text.is_empty(); - RepaintMode::Area(self.model.put(Some(text), double_width, self.cur_attrs.as_ref())) + RepaintMode::Area( + self.model + .put(Some(text), double_width, self.cur_attrs.as_ref()), + ) } pub fn on_clear(&mut self) -> RepaintMode {