nkxxll bbbdcb0271
feat(cli): add substring matching with --exact flag (#477)
fixes #368 

@alexpasmantier I tried to parse down the exact flag to the find method,
but I can't find an elegant way to do so because the channel creates its
own configurations for the matcher inside of the `new` method. I started
adding the exact flag to the new function of each of the channels but it
just does not seem right to do so. Do you have an idea on how to improve
the change? I would think of passing the config struct to the new
function and exposing the config of the channel for channel transitions,
but I'm not sure... 🤔

I have done it here for the stdin channel just to show you how it would
look like and it works fine😄! Looking forward to hearing your thoughts
on that 👍

ref issue: #368

---------

Co-authored-by: Alexandre Pasmantier <alex.pasmant@gmail.com>
2025-04-22 00:37:07 +02:00

176 lines
6.5 KiB
Rust

use clap::{Parser, Subcommand, ValueEnum};
#[allow(clippy::struct_excessive_bools)]
#[derive(Parser, Debug, Default)]
#[command(author, version, about, long_about = None)]
pub struct Cli {
/// Which channel shall we watch?
///
/// A list of the available channels can be displayed using the
/// `list-channels` command. The channel can also be changed from within
/// the application.
#[arg(
value_enum,
default_value = "files",
index = 1,
verbatim_doc_comment
)]
pub channel: String,
/// A preview command to use with the stdin channel.
///
/// If provided, the preview command will be executed and formatted using
/// the entry.
/// Example: "bat -n --color=always {}" (where {} will be replaced with
/// the entry)
///
/// Parts of the entry can be extracted positionally using the `delimiter`
/// option.
/// Example: "echo {0} {1}" will split the entry by the delimiter and pass
/// the first two fields to the command.
#[arg(short, long, value_name = "STRING", verbatim_doc_comment)]
pub preview: Option<String>,
/// Disable the preview panel entirely on startup.
#[arg(long, default_value = "false", verbatim_doc_comment)]
pub no_preview: bool,
/// The delimiter used to extract fields from the entry to provide to the
/// preview command.
///
/// See the `preview` option for more information.
#[arg(long, value_name = "STRING", default_value = " ", value_parser = delimiter_parser, verbatim_doc_comment)]
pub delimiter: String,
/// The application's tick rate.
///
/// The tick rate is the number of times the application will update per
/// second. This can be used to control responsiveness and CPU usage on
/// very slow machines or very fast ones but the default should be a good
/// compromise for most users.
#[arg(short, long, value_name = "FLOAT", verbatim_doc_comment)]
pub tick_rate: Option<f64>,
/// [DEPRECATED] Frame rate, i.e. number of frames to render per second.
///
/// This option is deprecated and will be removed in a future release.
#[arg(short, long, value_name = "FLOAT", verbatim_doc_comment)]
pub frame_rate: Option<f64>,
/// Keybindings to override the default keybindings.
///
/// This can be used to override the default keybindings with a custom subset
/// The keybindings are specified as a semicolon separated list of keybinding
/// expressions using the configuration file formalism.
///
/// Example: `tv --keybindings='quit="esc";select_next_entry=["down","ctrl-j"]'`
#[arg(short, long, value_name = "STRING", verbatim_doc_comment)]
pub keybindings: Option<String>,
/// Input text to pass to the channel to prefill the prompt.
///
/// This can be used to provide a default value for the prompt upon
/// startup.
#[arg(short, long, value_name = "STRING", verbatim_doc_comment)]
pub input: Option<String>,
/// Input fields header title
///
/// This can be used to give the input field a custom title e.g. the current
/// working directory.
/// The default value for the input header is the current channel.
#[arg(long, value_name = "STRING", verbatim_doc_comment)]
pub custom_header: Option<String>,
/// The working directory to start the application in.
///
/// This can be used to specify a different working directory for the
/// application to start in. This is useful when the application is
/// started from a different directory than the one the user wants to
/// interact with.
#[arg(value_name = "PATH", index = 2, verbatim_doc_comment)]
pub working_directory: Option<String>,
/// Try to guess the channel from the provided input prompt.
///
/// This can be used to automatically select a channel based on the input
/// prompt by using the `shell_integration` mapping in the configuration
/// file.
#[arg(long, value_name = "STRING", verbatim_doc_comment)]
pub autocomplete_prompt: Option<String>,
/// Use substring matching instead of fuzzy matching.
///
/// This will use substring matching instead of fuzzy matching when
/// searching for entries. This is useful when the user wants to search for
/// an exact match instead of a fuzzy match e.g. to improve performance.
#[arg(long, default_value = "false", verbatim_doc_comment)]
pub exact: bool,
/// Automatically select and output the first entry if there is only one
/// entry.
///
/// Note that most channels stream entries asynchronously which means that
/// knowing if there's only one entry will require waiting for the channel
/// to finish loading first.
///
/// For most channels and workloads this shouldn't be a problem since the
/// loading times are usually very short and will go unnoticed by the user.
#[arg(long, default_value = "false", verbatim_doc_comment)]
pub select_1: bool,
/// Disable the remote control.
///
/// This will disable the remote control panel and associated actions
/// entirely. This is useful when the remote control is not needed or
/// when the user wants `tv` to run in single-channel mode (e.g. when
/// using it as a file picker for a script or embedding it in a larger
/// application).
#[arg(long, default_value = "false", verbatim_doc_comment)]
pub no_remote: bool,
/// Disable the help panel.
///
/// This will disable the help panel and associated toggling actions
/// entirely. This is useful when the help panel is not needed or
/// when the user wants `tv` to run with a minimal interface (e.g. when
/// using it as a file picker for a script or embedding it in a larger
/// application).
#[arg(long, default_value = "false", verbatim_doc_comment)]
pub no_help: bool,
#[command(subcommand)]
pub command: Option<Command>,
}
#[derive(Subcommand, Debug, PartialEq, Clone)]
pub enum Command {
/// Lists the available channels.
ListChannels,
/// Initializes shell completion ("tv init zsh")
#[clap(name = "init")]
InitShell {
/// The shell for which to generate the autocompletion script
#[arg(value_enum)]
shell: Shell,
},
}
#[derive(Debug, Clone, Copy, PartialEq, ValueEnum)]
pub enum Shell {
Bash,
Zsh,
Fish,
PowerShell,
Cmd,
}
#[allow(clippy::unnecessary_wraps)]
fn delimiter_parser(s: &str) -> Result<String, String> {
Ok(match s {
"" => " ".to_string(),
"\\t" => "\t".to_string(),
_ => s.to_string(),
})
}