use crate::ported::commands::lint::{ArgAction, ArgParser, Argument};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum StrFunction {
Source,
Setenv,
Setup,
Command,
Uses,
}
impl StrFunction {
pub fn name(&self) -> &'static str {
match self {
StrFunction::Source => "source",
StrFunction::Setenv => "setenv",
StrFunction::Setup => "setup",
StrFunction::Command => "command",
StrFunction::Uses => "uses",
}
}
pub fn binding_function_name(&self) -> &'static str {
match self {
StrFunction::Source => "source_tmux_files",
StrFunction::Setenv => "init_tmux_environment",
StrFunction::Setup => "tmux_setup",
StrFunction::Command => "shell_command",
StrFunction::Uses => "uses",
}
}
pub fn call(&self) -> &'static str {
self.binding_function_name()
}
}
impl std::fmt::Display for StrFunction {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.name())
}
}
#[allow(non_snake_case)]
pub fn TMUX_ACTIONS() -> &'static [StrFunction] {
&[StrFunction::Source, StrFunction::Setenv, StrFunction::Setup]
}
#[allow(non_snake_case)]
pub fn SHELL_ACTIONS() -> &'static [StrFunction] {
&[StrFunction::Command, StrFunction::Uses]
}
pub fn tmux_action_from_name(name: &str) -> Option<StrFunction> {
match name {
"source" => Some(StrFunction::Source),
"setenv" => Some(StrFunction::Setenv),
"setup" => Some(StrFunction::Setup),
_ => None,
}
}
pub fn shell_action_from_name(name: &str) -> Option<StrFunction> {
match name {
"command" => Some(StrFunction::Command),
"uses" => Some(StrFunction::Uses),
_ => None,
}
}
pub struct ConfigArgParser {
pub argparser: ArgParser,
}
impl ConfigArgParser {
pub fn new(argparser: ArgParser) -> Self {
Self { argparser }
}
pub fn parse_args(&self, function: Option<&str>) -> Result<String, String> {
match function {
None => Err("too few arguments".to_string()),
Some(f) => Ok(f.to_string()),
}
}
}
pub fn get_argparser() -> ArgParser {
ArgParser {
description: "Script used to obtain powerline configuration.".to_string(),
arguments: vec![
Argument {
flags: vec!["-p".into(), "--config-path".into()],
action: ArgAction::Append,
metavar: Some("PATH".into()),
help: "Path to configuration directory. If it is present \
then configuration files will only be sought in the provided path. \
May be provided multiple times to search in a list of directories."
.into(),
},
Argument {
flags: vec!["tmux".into()],
action: ArgAction::Store,
metavar: Some("ACTION".into()),
help: "Tmux-specific commands: source / setenv / setup. \
If action is `source' then version-specific tmux configuration \
files are sourced, if it is `setenv' then special \
(prefixed with `_POWERLINE') tmux global environment variables \
are filled with data from powerline configuration. \
Action `setup' is just doing `setenv' then `source'."
.into(),
},
Argument {
flags: vec!["-s".into(), "--source".into()],
action: ArgAction::StoreTrue,
metavar: None,
help: "When using `setup': always use configuration file sourcing. \
By default this is determined automatically based on tmux \
version: this is the default for tmux 1.8 and below."
.into(),
},
Argument {
flags: vec!["-n".into(), "--no-source".into()],
action: ArgAction::StoreTrue,
metavar: None,
help: "When using `setup': in place of sourcing directly execute \
configuration files. That is, read each needed \
powerline-specific configuration file, substitute \
`$_POWERLINE_...' variables with appropriate values and run \
`tmux config line'. This is the default behaviour for \
tmux 1.9 and above."
.into(),
},
Argument {
flags: vec!["shell".into()],
action: ArgAction::Store,
metavar: Some("ACTION".into()),
help: "Shell-specific commands: command / uses. \
If action is `command' then preferred powerline command is \
output, if it is `uses' then powerline-config script will exit \
with 1 if specified component is disabled and 0 otherwise."
.into(),
},
Argument {
flags: vec!["component".into()],
action: ArgAction::Store,
metavar: Some("COMPONENT".into()),
help: "Only applicable for `uses' subcommand: makes `powerline-config' \
exit with 0 if specific component is enabled and with 1 otherwise. \
`tmux' component stands for tmux bindings \
(e.g. those that notify tmux about current directory changes), \
`prompt' component stands for shell prompt."
.into(),
},
Argument {
flags: vec!["--shell".into()],
action: ArgAction::Store,
metavar: Some("SHELL".into()),
help: "Shell for which query is run".into(),
},
],
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn str_function_names_match_upstream() {
assert_eq!(StrFunction::Source.name(), "source");
assert_eq!(StrFunction::Setenv.name(), "setenv");
assert_eq!(StrFunction::Setup.name(), "setup");
assert_eq!(StrFunction::Command.name(), "command");
assert_eq!(StrFunction::Uses.name(), "uses");
}
#[test]
fn str_function_display_round_trips_via_name() {
let s = format!("{}", StrFunction::Source);
assert_eq!(s, "source");
assert_eq!(tmux_action_from_name(&s), Some(StrFunction::Source));
}
#[test]
fn tmux_actions_has_three_entries() {
assert_eq!(TMUX_ACTIONS().len(), 3);
assert!(TMUX_ACTIONS().contains(&StrFunction::Source));
assert!(TMUX_ACTIONS().contains(&StrFunction::Setenv));
assert!(TMUX_ACTIONS().contains(&StrFunction::Setup));
}
#[test]
fn shell_actions_has_two_entries() {
assert_eq!(SHELL_ACTIONS().len(), 2);
assert!(SHELL_ACTIONS().contains(&StrFunction::Command));
assert!(SHELL_ACTIONS().contains(&StrFunction::Uses));
}
#[test]
fn tmux_action_lookup_unknown_returns_none() {
assert_eq!(tmux_action_from_name("xyz"), None);
}
#[test]
fn get_argparser_description_matches_upstream() {
let p = get_argparser();
assert_eq!(
p.description,
"Script used to obtain powerline configuration."
);
}
#[test]
fn get_argparser_includes_subcommand_handles() {
let p = get_argparser();
let flag_names: Vec<&str> = p
.arguments
.iter()
.flat_map(|a| a.flags.iter().map(|s| s.as_str()))
.collect();
assert!(flag_names.contains(&"--config-path"));
assert!(flag_names.contains(&"tmux"));
assert!(flag_names.contains(&"shell"));
assert!(flag_names.contains(&"component"));
}
#[test]
fn shell_action_lookup_command_and_uses() {
assert_eq!(
shell_action_from_name("command"),
Some(StrFunction::Command)
);
assert_eq!(shell_action_from_name("uses"), Some(StrFunction::Uses));
assert_eq!(shell_action_from_name("xyz"), None);
}
#[test]
fn str_function_binding_names_match_python_module_attrs() {
assert_eq!(
StrFunction::Source.binding_function_name(),
"source_tmux_files"
);
assert_eq!(
StrFunction::Setenv.binding_function_name(),
"init_tmux_environment"
);
assert_eq!(StrFunction::Setup.binding_function_name(), "tmux_setup");
assert_eq!(
StrFunction::Command.binding_function_name(),
"shell_command"
);
assert_eq!(StrFunction::Uses.binding_function_name(), "uses");
}
#[test]
fn str_function_call_returns_binding_function_name() {
assert_eq!(StrFunction::Source.call(), "source_tmux_files");
assert_eq!(StrFunction::Uses.call(), "uses");
}
#[test]
fn config_arg_parser_parse_args_requires_function() {
let parser = ConfigArgParser::new(get_argparser());
let err = parser.parse_args(None).unwrap_err();
assert_eq!(err, "too few arguments");
}
#[test]
fn config_arg_parser_parse_args_returns_function_when_set() {
let parser = ConfigArgParser::new(get_argparser());
let r = parser.parse_args(Some("tmux")).unwrap();
assert_eq!(r, "tmux");
}
#[test]
fn config_arg_parser_round_trips_underlying_argparser() {
let underlying = get_argparser();
let saved_desc = underlying.description.clone();
let saved_args_count = underlying.arguments.len();
let parser = ConfigArgParser::new(underlying);
assert_eq!(parser.argparser.description, saved_desc);
assert_eq!(parser.argparser.arguments.len(), saved_args_count);
}
}