mirror of
https://github.com/alexpasmantier/television.git
synced 2025-06-07 12:05:34 +00:00
feat(cli): add argument to start tv in another working directory (#132)
Resolves #111 --------- Co-authored-by: Alexandre Pasmantier <alex.pasmant@gmail.com>
This commit is contained in:
parent
3b8ab1fbd8
commit
882737d147
@ -1,3 +1,5 @@
|
||||
use std::path::Path;
|
||||
|
||||
use clap::{Parser, Subcommand};
|
||||
use color_eyre::{eyre::eyre, Result};
|
||||
|
||||
@ -14,8 +16,8 @@ use television_channels::{
|
||||
#[command(author, version = version(), about)]
|
||||
pub struct Cli {
|
||||
/// Which channel shall we watch?
|
||||
#[arg(value_enum, default_value = "files", value_parser = channel_parser)]
|
||||
pub channel: ParsedCliChannel,
|
||||
#[arg(value_enum, default_value = "files", index = 1)]
|
||||
pub channel: String,
|
||||
|
||||
/// Use a custom preview command (currently only supported by the stdin channel)
|
||||
#[arg(short, long, value_name = "STRING")]
|
||||
@ -40,11 +42,15 @@ pub struct Cli {
|
||||
#[arg(long, value_name = "STRING")]
|
||||
pub passthrough_keybindings: Option<String>,
|
||||
|
||||
/// The working directory to start in
|
||||
#[arg(value_name = "PATH", index = 2)]
|
||||
pub working_directory: Option<String>,
|
||||
|
||||
#[command(subcommand)]
|
||||
command: Option<Command>,
|
||||
}
|
||||
|
||||
#[derive(Subcommand, Debug)]
|
||||
#[derive(Subcommand, Debug, PartialEq)]
|
||||
pub enum Command {
|
||||
/// Lists available channels
|
||||
ListChannels,
|
||||
@ -58,6 +64,7 @@ pub struct PostProcessedCli {
|
||||
pub frame_rate: f64,
|
||||
pub passthrough_keybindings: Vec<String>,
|
||||
pub command: Option<Command>,
|
||||
pub working_directory: Option<String>,
|
||||
}
|
||||
|
||||
impl From<Cli> for PostProcessedCli {
|
||||
@ -74,17 +81,48 @@ impl From<Cli> for PostProcessedCli {
|
||||
delimiter: cli.delimiter.clone(),
|
||||
});
|
||||
|
||||
let channel: ParsedCliChannel;
|
||||
let working_directory: Option<String>;
|
||||
|
||||
match channel_parser(&cli.channel) {
|
||||
Ok(p) => {
|
||||
channel = p;
|
||||
working_directory = cli.working_directory;
|
||||
}
|
||||
Err(_) => {
|
||||
// if the path is provided as first argument and it exists, use it as the working
|
||||
// directory and default to the files channel
|
||||
if cli.working_directory.is_none()
|
||||
&& Path::new(&cli.channel).exists()
|
||||
{
|
||||
channel = ParsedCliChannel::Builtin(CliTvChannel::Files);
|
||||
working_directory = Some(cli.channel.clone());
|
||||
} else {
|
||||
unknown_channel_exit(&cli.channel);
|
||||
unreachable!();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Self {
|
||||
channel: cli.channel,
|
||||
channel,
|
||||
preview_command,
|
||||
tick_rate: cli.tick_rate,
|
||||
frame_rate: cli.frame_rate,
|
||||
passthrough_keybindings,
|
||||
command: cli.command,
|
||||
working_directory,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn unknown_channel_exit(channel: &str) {
|
||||
eprintln!("Unknown channel: {channel}\n");
|
||||
// print the list of channels
|
||||
list_channels();
|
||||
std::process::exit(1);
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum ParsedCliChannel {
|
||||
Builtin(CliTvChannel),
|
||||
@ -189,13 +227,14 @@ mod tests {
|
||||
#[allow(clippy::float_cmp)]
|
||||
fn test_from_cli() {
|
||||
let cli = Cli {
|
||||
channel: ParsedCliChannel::Builtin(CliTvChannel::Files),
|
||||
channel: "files".to_string(),
|
||||
preview: Some("bat -n --color=always {}".to_string()),
|
||||
delimiter: ":".to_string(),
|
||||
tick_rate: 50.0,
|
||||
frame_rate: 60.0,
|
||||
passthrough_keybindings: Some("q,ctrl-w,ctrl-t".to_string()),
|
||||
command: None,
|
||||
working_directory: Some("/home/user".to_string()),
|
||||
};
|
||||
|
||||
let post_processed_cli: PostProcessedCli = cli.into();
|
||||
@ -217,5 +256,36 @@ mod tests {
|
||||
post_processed_cli.passthrough_keybindings,
|
||||
vec!["q".to_string(), "ctrl-w".to_string(), "ctrl-t".to_string()]
|
||||
);
|
||||
assert_eq!(
|
||||
post_processed_cli.working_directory,
|
||||
Some("/home/user".to_string())
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[allow(clippy::float_cmp)]
|
||||
fn test_from_cli_no_args() {
|
||||
let cli = Cli {
|
||||
channel: ".".to_string(),
|
||||
preview: None,
|
||||
delimiter: ":".to_string(),
|
||||
tick_rate: 50.0,
|
||||
frame_rate: 60.0,
|
||||
passthrough_keybindings: None,
|
||||
command: None,
|
||||
working_directory: None,
|
||||
};
|
||||
|
||||
let post_processed_cli: PostProcessedCli = cli.into();
|
||||
|
||||
assert_eq!(
|
||||
post_processed_cli.channel,
|
||||
ParsedCliChannel::Builtin(CliTvChannel::Files)
|
||||
);
|
||||
assert_eq!(
|
||||
post_processed_cli.working_directory,
|
||||
Some(".".to_string())
|
||||
);
|
||||
assert_eq!(post_processed_cli.command, None);
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,6 @@
|
||||
use std::env;
|
||||
use std::io::{stdout, IsTerminal, Write};
|
||||
use std::path::Path;
|
||||
use std::process::exit;
|
||||
|
||||
use clap::Parser;
|
||||
@ -6,7 +8,7 @@ use cli::{list_channels, ParsedCliChannel, PostProcessedCli};
|
||||
use color_eyre::Result;
|
||||
use television_channels::channels::TelevisionChannel;
|
||||
use television_channels::entry::PreviewType;
|
||||
use tracing::{debug, info};
|
||||
use tracing::{debug, error, info};
|
||||
|
||||
use crate::app::App;
|
||||
use crate::cli::Cli;
|
||||
@ -45,6 +47,22 @@ async fn main() -> Result<()> {
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(working_directory) = args.working_directory {
|
||||
let path = Path::new(&working_directory);
|
||||
if !path.exists() {
|
||||
error!(
|
||||
"Working directory \"{}\" does not exist",
|
||||
&working_directory
|
||||
);
|
||||
println!(
|
||||
"Error: Working directory \"{}\" does not exist",
|
||||
&working_directory
|
||||
);
|
||||
exit(1);
|
||||
}
|
||||
env::set_current_dir(path)?;
|
||||
}
|
||||
|
||||
match App::new(
|
||||
{
|
||||
if is_readable_stdin() {
|
||||
|
Loading…
x
Reference in New Issue
Block a user