neovim-gtk/src/main.rs

247 lines
6.0 KiB
Rust
Raw Permalink Normal View History

2018-03-26 08:24:36 +00:00
#![windows_subsystem = "windows"]
#[cfg(unix)]
extern crate unix_daemonize;
2018-02-16 09:57:26 +00:00
extern crate cairo;
extern crate env_logger;
2016-03-31 13:52:22 +00:00
extern crate gdk;
2016-05-05 07:23:04 +00:00
extern crate gdk_sys;
2018-02-16 09:57:26 +00:00
extern crate gio;
#[macro_use]
2016-03-28 14:14:10 +00:00
extern crate glib;
extern crate glib_sys as glib_ffi;
2017-08-25 15:32:30 +00:00
extern crate gobject_sys as gobject_ffi;
2018-02-16 09:57:26 +00:00
extern crate gtk;
extern crate gtk_sys;
extern crate htmlescape;
#[macro_use]
extern crate lazy_static;
#[macro_use]
2018-02-16 09:57:26 +00:00
extern crate log;
extern crate neovim_lib;
2017-03-05 22:28:07 +00:00
extern crate pango;
2018-02-16 09:57:26 +00:00
extern crate pango_cairo_sys;
extern crate pango_sys;
2017-03-05 22:28:07 +00:00
extern crate pangocairo;
extern crate percent_encoding;
2016-04-02 20:00:18 +00:00
extern crate phf;
extern crate regex;
2018-04-09 20:11:15 +00:00
extern crate rmpv;
extern crate unicode_segmentation;
2018-04-09 20:11:15 +00:00
extern crate unicode_width;
2017-05-13 14:31:19 +00:00
2018-04-10 18:34:13 +00:00
extern crate atty;
2017-10-19 14:04:58 +00:00
extern crate serde;
2017-05-13 14:31:19 +00:00
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
2018-02-16 09:57:26 +00:00
extern crate toml;
2016-03-16 14:39:53 +00:00
mod sys;
mod nvim_config;
2017-10-19 14:04:58 +00:00
mod dirs;
mod theme;
2017-08-23 09:45:56 +00:00
mod color;
2017-07-08 11:02:56 +00:00
mod value;
2017-07-08 20:45:55 +00:00
mod mode;
2016-03-19 08:47:23 +00:00
mod ui_model;
#[macro_use]
2016-03-16 15:25:25 +00:00
mod ui;
2017-10-29 19:16:55 +00:00
mod plug_manager;
mod nvim;
mod render;
mod shell;
2016-04-04 10:14:57 +00:00
mod input;
2017-03-13 15:03:32 +00:00
mod settings;
2017-03-22 15:37:18 +00:00
mod cursor;
2017-11-18 12:56:37 +00:00
mod cmd_line;
2017-04-01 10:00:14 +00:00
mod shell_dlg;
mod popup_menu;
2017-05-13 14:31:19 +00:00
mod project;
2017-05-27 16:50:25 +00:00
mod tabline;
mod error;
2018-03-11 12:49:13 +00:00
mod file_browser;
2018-02-25 14:54:15 +00:00
mod subscriptions;
mod misc;
2016-03-16 14:39:53 +00:00
#[cfg(unix)]
use unix_daemonize::{daemonize_redirect, ChdirMode};
2017-03-06 13:58:10 +00:00
use std::env;
2018-04-09 20:11:15 +00:00
use std::io::Read;
use std::cell::RefCell;
use std::time::Duration;
use std::str::FromStr;
use gio::prelude::*;
2016-05-05 14:27:45 +00:00
use ui::Ui;
2017-03-16 10:18:13 +00:00
use shell::ShellOptions;
const BIN_PATH_ARG: &str = "--nvim-bin-path";
const TIMEOUT_ARG: &str = "--timeout";
2018-02-16 09:57:26 +00:00
const DISABLE_WIN_STATE_RESTORE: &str = "--disable-win-restore";
const NO_FORK: &str = "--no-fork";
2016-03-16 15:25:25 +00:00
fn main() {
env_logger::init();
2017-04-03 11:17:06 +00:00
2018-04-09 20:11:15 +00:00
let input_data = RefCell::new(read_piped_input());
2017-12-31 09:47:50 +00:00
let app_flags = gio::ApplicationFlags::HANDLES_OPEN | gio::ApplicationFlags::NON_UNIQUE;
2017-06-08 14:17:08 +00:00
2018-02-10 09:16:28 +00:00
glib::set_program_name(Some("NeovimGtk"));
2017-05-13 21:30:34 +00:00
let app = if cfg!(debug_assertions) {
gtk::Application::new(Some("org.daa.NeovimGtkDebug"), app_flags)
} else {
gtk::Application::new(Some("org.daa.NeovimGtk"), app_flags)
}.expect("Failed to initialize GTK application");
2017-03-06 13:58:10 +00:00
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();
2018-04-09 20:11:15 +00:00
new_window_action.connect_activate(move |_, _| activate(&app_ref, None));
app.add_action(&new_window_action);
2017-03-06 13:58:10 +00:00
gtk::Window::set_default_icon_name("org.daa.NeovimGtk");
let argv: Vec<String> = env::args()
.take_while(|a| *a != "--")
.filter(|a| !a.starts_with(BIN_PATH_ARG))
.filter(|a| !a.starts_with(TIMEOUT_ARG))
2018-02-16 09:57:26 +00:00
.filter(|a| !a.starts_with(DISABLE_WIN_STATE_RESTORE))
.filter(|a| !a.starts_with(NO_FORK))
.collect();
#[cfg(unix)] {
// fork to background by default
let want_fork = env::args()
.take_while(|a| *a != "--")
.skip(1)
.find(|a| a.starts_with(NO_FORK))
.is_none();
if want_fork {
daemonize_redirect(Some("/tmp/nvim-gtk_stdout.log"),
Some("/tmp/nvim-gtk_stderr.log"),
ChdirMode::NoChdir)
.unwrap();
}
}
2017-07-11 09:33:55 +00:00
app.run(&argv);
2017-03-06 13:58:10 +00:00
}
fn collect_args_for_nvim() -> Vec<String> {
std::env::args().skip_while(|a| *a != "--").skip(1).collect()
}
2017-06-08 14:17:08 +00:00
fn open(app: &gtk::Application, files: &[gio::File], _: &str) {
2018-03-20 17:43:31 +00:00
let files_list: Vec<String> = files
.into_iter()
.filter_map(|f| f.get_path()?.to_str().map(str::to_owned))
.collect();
let mut ui = Ui::new(ShellOptions::new(
nvim_bin_path(std::env::args()),
files_list,
nvim_timeout(std::env::args()),
collect_args_for_nvim(),
2018-04-09 20:11:15 +00:00
None,
2018-03-20 17:43:31 +00:00
));
ui.init(app, !nvim_disable_win_state(std::env::args()));
2017-06-08 14:17:08 +00:00
}
2018-04-09 20:11:15 +00:00
fn activate(app: &gtk::Application, input_data: Option<String>) {
let mut ui = Ui::new(ShellOptions::new(
nvim_bin_path(std::env::args()),
2018-03-20 17:43:31 +00:00
Vec::new(),
nvim_timeout(std::env::args()),
collect_args_for_nvim(),
2018-04-09 20:11:15 +00:00
input_data,
));
2018-02-16 09:57:26 +00:00
ui.init(app, !nvim_disable_win_state(std::env::args()));
2016-03-16 14:39:53 +00:00
}
fn nvim_bin_path<I>(mut args: I) -> Option<String>
where
I: Iterator<Item = String>,
{
2018-02-16 09:57:26 +00:00
args.find(|a| a.starts_with(BIN_PATH_ARG))
.and_then(|p| p.split('=').nth(1).map(str::to_owned))
}
fn nvim_timeout<I>(mut args: I) -> Option<Duration>
where
I: Iterator<Item = String>,
{
args.find(|a| a.starts_with(TIMEOUT_ARG))
.and_then(|p| p.split('=').nth(1).map(str::to_owned))
.and_then(|timeout| match u64::from_str(&timeout) {
Ok(timeout) => Some(timeout),
Err(err) => {
error!("Can't convert timeout argument to integer: {}", err);
None
}
})
.map(|timeout| Duration::from_secs(timeout))
}
2018-02-16 09:57:26 +00:00
fn nvim_disable_win_state<I>(mut args: I) -> bool
where
I: Iterator<Item = String>,
{
args.find(|a| a.starts_with(DISABLE_WIN_STATE_RESTORE))
.map(|_| true)
.unwrap_or(false)
}
2018-04-09 20:11:15 +00:00
fn read_piped_input() -> Option<String> {
2018-04-10 18:34:13 +00:00
if atty::isnt(atty::Stream::Stdin) {
2018-04-09 20:11:15 +00:00
let mut buf = String::new();
match std::io::stdin().read_to_string(&mut buf) {
Ok(size) if size > 0 => Some(buf),
Ok(_) => None,
2018-04-09 20:11:15 +00:00
Err(err) => {
error!("Error read stdin {}", err);
None
}
}
} else {
None
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_bin_path_arg() {
assert_eq!(
Some("/test_path".to_string()),
nvim_bin_path(
vec!["neovim-gtk", "--nvim-bin-path=/test_path"]
.iter()
.map(|s| s.to_string()),
)
);
}
#[test]
fn test_timeout_arg() {
assert_eq!(
Some(Duration::from_secs(100)),
2018-02-16 09:57:26 +00:00
nvim_timeout(
vec!["neovim-gtk", "--timeout=100"]
.iter()
.map(|s| s.to_string(),)
)
);
}
}