add tests for the cmdline parsing

macos-click-through
Keith Simmons 3 years ago
parent 5630d5240e
commit 401d1a88a2

@ -123,9 +123,7 @@ pub fn build_neovide_command(channel: u64, num_args: u64, command: &str, event:
pub fn create_nvim_command() -> Command { pub fn create_nvim_command() -> Command {
let mut cmd = build_nvim_cmd(); let mut cmd = build_nvim_cmd();
cmd.arg("--embed") cmd.arg("--embed").args(SETTINGS.get::<CmdLineSettings>().neovim_args.iter());
.args(SETTINGS.get::<CmdLineSettings>().neovim_args.iter())
.args(SETTINGS.get::<CmdLineSettings>().files_to_open.iter());
info!("Starting neovim with: {:?}", cmd); info!("Starting neovim with: {:?}", cmd);

@ -5,21 +5,22 @@ use clap::{App, Arg};
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct CmdLineSettings { pub struct CmdLineSettings {
pub verbosity: u64, // Pass through arguments
pub log_to_file: bool,
pub neovim_args: Vec<String>, pub neovim_args: Vec<String>,
pub neovim_bin: Option<String>, // Command-line arguments only
pub files_to_open: Vec<String>,
pub no_fork: bool,
pub no_idle: bool,
pub srgb: bool,
pub geometry: Dimensions, pub geometry: Dimensions,
pub wsl: bool, pub log_to_file: bool,
pub no_fork: bool,
pub remote_tcp: Option<String>, pub remote_tcp: Option<String>,
pub multi_grid: bool, pub wsl: bool,
pub maximized: bool, // Command-line flags with environment variable fallback
pub frameless: bool, pub frameless: bool,
pub maximized: bool,
pub multi_grid: bool,
pub no_idle: bool,
pub srgb: bool,
// Command-line arguments with environment variable fallback
pub neovim_bin: Option<String>,
pub wayland_app_id: String, pub wayland_app_id: String,
pub x11_wm_class: String, pub x11_wm_class: String,
} }
@ -27,37 +28,47 @@ pub struct CmdLineSettings {
impl Default for CmdLineSettings { impl Default for CmdLineSettings {
fn default() -> Self { fn default() -> Self {
Self { Self {
verbosity: 0, // Pass through arguments
log_to_file: false,
neovim_bin: None,
neovim_args: vec![], neovim_args: vec![],
files_to_open: vec![], // Command-line arguments only
no_fork: false,
no_idle: false,
srgb: true,
geometry: DEFAULT_WINDOW_GEOMETRY, geometry: DEFAULT_WINDOW_GEOMETRY,
wsl: false, log_to_file: false,
no_fork: false,
remote_tcp: None, remote_tcp: None,
multi_grid: false, wsl: false,
maximized: false, // Command-line flags with environment variable fallback
frameless: false, frameless: false,
maximized: false,
multi_grid: false,
no_idle: false,
srgb: true,
// Command-line arguments with environment variable fallback
neovim_bin: None,
wayland_app_id: String::new(), wayland_app_id: String::new(),
x11_wm_class: String::new(), x11_wm_class: String::new(),
} }
} }
} }
pub fn handle_command_line_arguments() -> Result<(), String> { pub fn handle_command_line_arguments(args: Vec<String>) -> Result<(), String> {
let clapp = App::new("Neovide") let clapp = App::new("Neovide")
.version(crate_version!()) .version(crate_version!())
.author(crate_authors!()) .author(crate_authors!())
.about(crate_description!()) .about(crate_description!())
// Pass through arguments
.arg( .arg(
Arg::with_name("verbosity") Arg::with_name("neovim_args")
.short("v")
.multiple(true) .multiple(true)
.help("Increase verbosity level (repeatable up to 4 times; implies --nofork)"), .takes_value(true)
.last(true)
.help("Specify Arguments to pass down to neovim"),
)
// Command-line arguments only
.arg(
Arg::with_name("geometry")
.long("geometry")
.takes_value(true)
.help("Specify the Geometry of the window"),
) )
.arg( .arg(
Arg::with_name("log_to_file") Arg::with_name("log_to_file")
@ -70,14 +81,21 @@ pub fn handle_command_line_arguments() -> Result<(), String> {
.help("Do not detach process from terminal"), .help("Do not detach process from terminal"),
) )
.arg( .arg(
Arg::with_name("noidle") Arg::with_name("remote_tcp")
.long("noidle") .long("remote-tcp")
.help("Render every frame. Takes more power and cpu time but possibly fixes animation issues"), .takes_value(true)
.help("Connect to Remote TCP"),
) )
.arg( .arg(
Arg::with_name("srgb") Arg::with_name("wsl")
.long("srgb") .long("wsl")
.help("Use standard color space to initialize the window. Swapping this variable sometimes fixes issues on startup"), .help("Run in WSL")
)
// Command-line flags with environment variable fallback
.arg(
Arg::with_name("frameless")
.long("frameless")
.help("Removes the window frame. NOTE: Window might not be resizable after this setting is enabled.")
) )
.arg( .arg(
Arg::with_name("maximized") Arg::with_name("maximized")
@ -90,46 +108,22 @@ pub fn handle_command_line_arguments() -> Result<(), String> {
.help("Enable Multigrid"), .help("Enable Multigrid"),
) )
.arg( .arg(
Arg::with_name("frameless") Arg::with_name("noidle")
.long("frameless") .long("noidle")
.help("Removes the window frame. NOTE: Window might not be resizable after this setting is enabled.") .help("Render every frame. Takes more power and cpu time but possibly fixes animation issues"),
)
.arg(
Arg::with_name("wsl")
.long("wsl")
.help("Run in WSL")
)
.arg(
Arg::with_name("remote_tcp")
.long("remote-tcp")
.takes_value(true)
.help("Connect to Remote TCP"),
)
.arg(
Arg::with_name("geometry")
.long("geometry")
.takes_value(true)
.help("Specify the Geometry of the window"),
) )
.arg( .arg(
Arg::with_name("files") Arg::with_name("srgb")
.multiple(true) .long("srgb")
.takes_value(true) .help("Use standard color space to initialize the window. Swapping this variable sometimes fixes issues on startup"),
.help("Files to open"),
) )
// Command-line arguments with environment variable fallback
.arg( .arg(
Arg::with_name("neovim_bin") Arg::with_name("neovim_bin")
.long("neovim-bin") .long("neovim-bin")
.takes_value(true) .takes_value(true)
.help("Specify path to neovim"), .help("Specify path to neovim"),
) )
.arg(
Arg::with_name("neovim_args")
.multiple(true)
.takes_value(true)
.last(true)
.help("Specify Arguments to pass down to neovim"),
)
.arg( .arg(
Arg::with_name("wayland_app_id") Arg::with_name("wayland_app_id")
.long("wayland-app-id") .long("wayland-app-id")
@ -141,53 +135,161 @@ pub fn handle_command_line_arguments() -> Result<(), String> {
.takes_value(true) .takes_value(true)
); );
let matches = clapp.get_matches(); let matches = clapp.get_matches_from(args);
/* /*
* Integrate Environment Variables as Defaults to the command-line ones. * Integrate Environment Variables as Defaults to the command-line ones.
* *
* NEOVIM_BIN * If the command-line argument is not set, the environment variable is used.
* NEOVIDE_MULTIGRID || --multigrid
*/ */
SETTINGS.set::<CmdLineSettings>(&CmdLineSettings { SETTINGS.set::<CmdLineSettings>(&CmdLineSettings {
verbosity: matches.occurrences_of("verbosity"), // Pass through arguments
log_to_file: matches.is_present("log_to_file"),
neovim_args: matches neovim_args: matches
.values_of("neovim_args") .values_of("neovim_args")
.map(|opt| opt.map(|v| v.to_owned()).collect()) .map(|opt| opt.map(|v| v.to_owned()).collect())
.unwrap_or_default(), .unwrap_or_default(),
neovim_bin: match std::env::var("NEOVIM_BIN") { // Command-line arguments only
Ok(val) => Some(val),
Err(_) => matches.value_of("neovim_bin").map(|b| b.to_string()),
},
files_to_open: matches
.values_of("files")
.map(|opt| opt.map(|v| v.to_owned()).collect())
.unwrap_or_default(),
no_fork: matches.is_present("nofork") || matches.is_present("verbosity"),
no_idle: matches.is_present("noidle") || std::env::var("NEOVIDE_NOIDLE").is_ok(),
srgb: matches.is_present("srgb") || std::env::var("NEOVIDE_NO_SRGB").is_err(),
geometry: parse_window_geometry(matches.value_of("geometry").map(|i| i.to_owned()))?, geometry: parse_window_geometry(matches.value_of("geometry").map(|i| i.to_owned()))?,
wsl: matches.is_present("wsl"), log_to_file: matches.is_present("log_to_file"),
no_fork: matches.is_present("nofork"),
remote_tcp: matches.value_of("remote_tcp").map(|i| i.to_owned()), remote_tcp: matches.value_of("remote_tcp").map(|i| i.to_owned()),
multi_grid: std::env::var("NEOVIDE_MULTIGRID").is_ok() || matches.is_present("multi_grid"), wsl: matches.is_present("wsl"),
maximized: matches.is_present("maximized") || std::env::var("NEOVIDE_MAXIMIZED").is_ok(), // Command-line flags with environment variable fallback
frameless: matches.is_present("frameless") || std::env::var("NEOVIDE_FRAMELESS").is_ok(), frameless: matches.is_present("frameless") || std::env::var("NEOVIDE_FRAMELESS").is_ok(),
wayland_app_id: match std::env::var("NEOVIDE_APP_ID") { maximized: matches.is_present("maximized") || std::env::var("NEOVIDE_MAXIMIZED").is_ok(),
Ok(val) => val, multi_grid: matches.is_present("multi_grid") || std::env::var("NEOVIDE_MULTIGRID").is_ok(),
Err(_) => matches no_idle: matches.is_present("noidle") || std::env::var("NEOVIDE_NOIDLE").is_ok(),
.value_of("wayland_app_id") srgb: matches.is_present("srgb") || std::env::var("NEOVIDE_NO_SRGB").is_err(),
.unwrap_or("neovide") // Command-line arguments with environment variable fallback
.to_string(), neovim_bin: matches
}, .value_of("neovim_bin")
x11_wm_class: match std::env::var("NEOVIDE_WM_CLASS") { .map(|v| v.to_owned())
Ok(val) => val, .or_else(|| std::env::var("NEOVIM_BIN").ok()),
Err(_) => matches wayland_app_id: matches
.value_of("x11_wm_class") .value_of("wayland_app_id")
.unwrap_or("neovide") .map(|v| v.to_owned())
.to_string(), .or_else(|| std::env::var("NEOVIDE_APP_ID").ok())
}, .unwrap_or("neovide".to_owned()),
x11_wm_class: matches
.value_of("x11_wm_class")
.map(|v| v.to_owned())
.or_else(|| std::env::var("NEOVIDE_X11_WM_CLASS").ok())
.unwrap_or("neovide".to_owned()),
}); });
Ok(()) Ok(())
} }
#[cfg(test)]
mod tests {
use std::sync::Mutex;
use std::env::set_var;
use lazy_static::lazy_static;
use super::*;
// Use a mutex to ensure that the settings are initialized and accessed in series
lazy_static! {
static ref ACCESSING_SETTINGS: Mutex<bool> = Mutex::new(false);
}
#[test]
fn test_neovim_passthrough() {
let args: Vec<String> = vec![
"neovide",
"--",
"--clean",
].iter()
.map(|s| s.to_string())
.collect();
let _accessing_settings = ACCESSING_SETTINGS.lock().unwrap();
handle_command_line_arguments(args).expect("Could not parse arguments");
assert_eq!(SETTINGS.get::<CmdLineSettings>().neovim_args, vec!["--clean"]);
}
#[test]
fn test_geometry() {
let args: Vec<String> = vec![
"neovide",
"--geometry=42x24",
].iter()
.map(|s| s.to_string())
.collect();
let _accessing_settings = ACCESSING_SETTINGS.lock().unwrap();
handle_command_line_arguments(args).expect("Could not parse arguments");
assert_eq!(SETTINGS.get::<CmdLineSettings>().geometry, Dimensions { width: 42, height: 24 });
}
#[test]
fn test_log_to_file() {
let args: Vec<String> = vec![
"neovide",
"--log",
].iter()
.map(|s| s.to_string())
.collect();
let _accessing_settings = ACCESSING_SETTINGS.lock().unwrap();
handle_command_line_arguments(args).expect("Could not parse arguments");
assert_eq!(SETTINGS.get::<CmdLineSettings>().log_to_file, true);
}
#[test]
fn test_frameless_flag() {
let args: Vec<String> = vec![
"neovide",
"--frameless",
].iter()
.map(|s| s.to_string())
.collect();
let _accessing_settings = ACCESSING_SETTINGS.lock().unwrap();
handle_command_line_arguments(args).expect("Could not parse arguments");
assert_eq!(SETTINGS.get::<CmdLineSettings>().frameless, true);
}
#[test]
fn test_frameless_environment_variable() {
let args: Vec<String> = vec![
"neovide",
].iter()
.map(|s| s.to_string())
.collect();
let _accessing_settings = ACCESSING_SETTINGS.lock().unwrap();
set_var("NEOVIDE_FRAMELESS", "true");
handle_command_line_arguments(args).expect("Could not parse arguments");
assert_eq!(SETTINGS.get::<CmdLineSettings>().frameless, true);
}
#[test]
fn test_neovim_bin_arg() {
let args: Vec<String> = vec![
"neovide",
"--neovim-bin",
"foo",
].iter()
.map(|s| s.to_string())
.collect();
let _accessing_settings = ACCESSING_SETTINGS.lock().unwrap();
handle_command_line_arguments(args).expect("Could not parse arguments");
assert_eq!(SETTINGS.get::<CmdLineSettings>().neovim_bin, Some("foo".to_owned()));
}
#[test]
fn test_neovim_bin_environment_variable() {
let args: Vec<String> = vec![
"neovide",
].iter()
.map(|s| s.to_string())
.collect();
let _accessing_settings = ACCESSING_SETTINGS.lock().unwrap();
set_var("NEOVIM_BIN", "foo");
handle_command_line_arguments(args).expect("Could not parse arguments");
assert_eq!(SETTINGS.get::<CmdLineSettings>().neovim_bin, Some("foo".to_owned()));
}
}

@ -31,6 +31,7 @@ extern crate derive_new;
extern crate lazy_static; extern crate lazy_static;
use std::sync::mpsc::channel; use std::sync::mpsc::channel;
use std::env::args;
use log::trace; use log::trace;
use tokio::sync::mpsc::unbounded_channel; use tokio::sync::mpsc::unbounded_channel;
@ -117,7 +118,7 @@ fn main() {
// properly or updates to the graphics are pushed to the screen. // properly or updates to the graphics are pushed to the screen.
//Will exit if -h or -v //Will exit if -h or -v
if let Err(err) = cmd_line::handle_command_line_arguments() { if let Err(err) = cmd_line::handle_command_line_arguments(args().collect()) {
eprintln!("{}", err); eprintln!("{}", err);
return; return;
} }
@ -179,12 +180,6 @@ fn main() {
pub fn init_logger() { pub fn init_logger() {
let settings = SETTINGS.get::<CmdLineSettings>(); let settings = SETTINGS.get::<CmdLineSettings>();
let verbosity = match settings.verbosity {
0 => "warn",
1 => "info",
2 => "debug",
_ => "trace",
};
let logger = match settings.log_to_file { let logger = match settings.log_to_file {
true => Logger::with_env_or_str("neovide") true => Logger::with_env_or_str("neovide")
.duplicate_to_stderr(Duplicate::Error) .duplicate_to_stderr(Duplicate::Error)
@ -194,7 +189,7 @@ pub fn init_logger() {
Naming::Timestamps, Naming::Timestamps,
Cleanup::KeepLogFiles(1), Cleanup::KeepLogFiles(1),
), ),
false => Logger::with_env_or_str(format!("neovide = {}", verbosity)), false => Logger::with_env_or_str(format!("neovide = {}", "trace")),
}; };
logger.start().expect("Could not start logger"); logger.start().expect("Could not start logger");
} }

Loading…
Cancel
Save