mirror of
https://github.com/sayanarijit/xplr.git
synced 2024-09-11 11:05:39 +03:00
Implement support path selection and force focus
Examples: ```bash xplr $PWD /path/to/select1 path/to/select2 xplr -- $PWD /path/to/select1 path/to/select2 echo -e "$PWD\n/path/to/select1\npath/to/select2" | xplr - ls -d /path/to/select1 path/to/select2 | xplr $PWD - ```
This commit is contained in:
parent
91675e28af
commit
2d7158afc0
@ -13,25 +13,25 @@ fn main() {
|
||||
|
||||
if cli.help {
|
||||
let usage = r###"
|
||||
xplr [FLAG]... [OPTION]... [PATH]"###;
|
||||
xplr [FLAG]... [OPTION]... [FOCUS] [SELECTION]..."###;
|
||||
|
||||
let flags = r###"
|
||||
- Reads path from stdin
|
||||
- Reads paths from stdin
|
||||
-- Denotes the end of command-line flags and options
|
||||
--read-only Enables read-only mode (config.general.read_only)
|
||||
-h, --help Prints help information
|
||||
-V, --version Prints version information"###;
|
||||
|
||||
let options = r###"
|
||||
-c, --config <PATH> Specifies a custom config file (default is
|
||||
"$HOME/.config/xplr/init.lua")
|
||||
-C, --extra-config <PATH>... Specifies extra config files to load
|
||||
--on-load <MESSAGE>... Sends messages when xplr loads
|
||||
--select <PATH>... Selects the given paths.
|
||||
--force-focus Focuses the given path, instead of entering it."###;
|
||||
-c, --config <PATH> Specifies a custom config file (default is
|
||||
"$HOME/.config/xplr/init.lua")
|
||||
-C, --extra-config <PATH>... Specifies extra config files to load
|
||||
--on-load <MESSAGE>... Sends messages when xplr loads
|
||||
--force-focus Focuses the given path, instead of entering it."###;
|
||||
|
||||
let args = r###"
|
||||
<PATH> Path to focus on, or enter if directory"###;
|
||||
<FOCUS> Path to focus on, or enter if directory, (default is `.`)
|
||||
<SELECTION>... Paths to select, requires <FOCUS> to be set explicitely"###;
|
||||
|
||||
let help = format!(
|
||||
"xplr {}\n{}\n{}\n\nUSAGE:{}\n\nFLAGS:{}\n\nOPTIONS:{}\n\nARGS:{}",
|
||||
|
141
src/cli.rs
141
src/cli.rs
@ -1,8 +1,8 @@
|
||||
use anyhow::Result;
|
||||
use std::collections::VecDeque;
|
||||
use std::env;
|
||||
use std::io::{BufRead, BufReader};
|
||||
use std::path::PathBuf;
|
||||
use std::{env, io};
|
||||
|
||||
use crate::app;
|
||||
|
||||
@ -12,100 +12,93 @@ pub struct Cli {
|
||||
pub version: bool,
|
||||
pub help: bool,
|
||||
pub read_only: bool,
|
||||
pub path: Option<PathBuf>,
|
||||
pub force_focus: bool,
|
||||
pub config: Option<PathBuf>,
|
||||
pub extra_config: Vec<PathBuf>,
|
||||
pub on_load: Vec<app::ExternalMsg>,
|
||||
pub select: Vec<PathBuf>,
|
||||
pub paths: Vec<PathBuf>,
|
||||
}
|
||||
|
||||
impl Cli {
|
||||
fn read_path(&mut self, arg: &str) {
|
||||
if arg.is_empty() {
|
||||
return;
|
||||
};
|
||||
|
||||
let path = PathBuf::from(arg);
|
||||
if path.exists() {
|
||||
self.paths.push(path);
|
||||
};
|
||||
}
|
||||
|
||||
/// Parse arguments from the command-line
|
||||
pub fn parse(args: env::Args) -> Result<Self> {
|
||||
let mut args: VecDeque<String> = args.skip(1).collect();
|
||||
let mut cli = Self::default();
|
||||
|
||||
let mut flag_ends = false;
|
||||
|
||||
while let Some(arg) = args.pop_front() {
|
||||
match arg.as_str() {
|
||||
// Flags
|
||||
"-" => {
|
||||
let mut path = String::new();
|
||||
if io::stdin().read_line(&mut path).is_ok() {
|
||||
cli.path =
|
||||
Some(path.trim_end_matches("\r\n").trim_end_matches('\n').into());
|
||||
};
|
||||
}
|
||||
|
||||
"-h" | "--help" => {
|
||||
cli.help = true;
|
||||
}
|
||||
|
||||
"-V" | "--version" => {
|
||||
cli.version = true;
|
||||
}
|
||||
|
||||
"--" => {
|
||||
if cli.path.is_none() {
|
||||
cli.path = args.pop_front().map(PathBuf::from);
|
||||
}
|
||||
return Ok(cli);
|
||||
}
|
||||
|
||||
// Options
|
||||
"-c" | "--config" => cli.config = args.pop_front().map(PathBuf::from),
|
||||
|
||||
"-C" | "--extra-config" => {
|
||||
while let Some(path) = args.pop_front() {
|
||||
if path.starts_with('-') {
|
||||
args.push_front(path);
|
||||
break;
|
||||
} else {
|
||||
cli.extra_config.push(PathBuf::from(path));
|
||||
if flag_ends {
|
||||
cli.read_path(&arg);
|
||||
} else {
|
||||
match arg.as_str() {
|
||||
// Flags
|
||||
"-" => {
|
||||
for path in BufReader::new(std::io::stdin())
|
||||
.lines()
|
||||
.filter_map(|l| l.ok())
|
||||
{
|
||||
cli.read_path(&path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
"--read-only" => cli.read_only = true,
|
||||
|
||||
"--on-load" => {
|
||||
while let Some(msg) = args.pop_front() {
|
||||
if msg.starts_with('-') {
|
||||
args.push_front(msg);
|
||||
break;
|
||||
} else {
|
||||
cli.on_load.push(serde_yaml::from_str(&msg)?);
|
||||
}
|
||||
"-h" | "--help" => {
|
||||
cli.help = true;
|
||||
}
|
||||
}
|
||||
"--select" => {
|
||||
while let Some(path) = args.pop_front() {
|
||||
if path.starts_with('-') && path != "-" {
|
||||
for path in BufReader::new(std::io::stdin()).lines() {
|
||||
cli.select.push(PathBuf::from(path?));
|
||||
|
||||
"-V" | "--version" => {
|
||||
cli.version = true;
|
||||
}
|
||||
|
||||
"--" => {
|
||||
flag_ends = true;
|
||||
}
|
||||
|
||||
// Options
|
||||
"-c" | "--config" => cli.config = args.pop_front().map(PathBuf::from),
|
||||
|
||||
"-C" | "--extra-config" => {
|
||||
while let Some(path) = args.pop_front() {
|
||||
if path.starts_with('-') {
|
||||
args.push_front(path);
|
||||
break;
|
||||
} else {
|
||||
cli.extra_config.push(PathBuf::from(path));
|
||||
}
|
||||
break;
|
||||
} else {
|
||||
cli.select.push(PathBuf::from(path));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
"--force-focus" => {
|
||||
let path = cli
|
||||
.path
|
||||
.as_ref()
|
||||
.cloned()
|
||||
.or_else(|| args.pop_front().map(PathBuf::from))
|
||||
.unwrap_or_default();
|
||||
cli.on_load.push(app::ExternalMsg::FocusPath(
|
||||
path.to_string_lossy().to_string(),
|
||||
));
|
||||
}
|
||||
"--read-only" => cli.read_only = true,
|
||||
|
||||
// path
|
||||
path => {
|
||||
if cli.path.is_none() {
|
||||
cli.path = Some(path.into());
|
||||
"--on-load" => {
|
||||
while let Some(msg) = args.pop_front() {
|
||||
if msg.starts_with('-') {
|
||||
args.push_front(msg);
|
||||
break;
|
||||
} else {
|
||||
cli.on_load.push(serde_yaml::from_str(&msg)?);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
"--force-focus" => {
|
||||
cli.force_focus = true;
|
||||
}
|
||||
|
||||
// path
|
||||
path => {
|
||||
cli.read_path(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -124,13 +124,14 @@ impl Runner {
|
||||
/// Create a new runner object passing the given arguments
|
||||
pub fn from_cli(cli: Cli) -> Result<Self> {
|
||||
let basedir = std::env::current_dir()?;
|
||||
let mut pwd = cli
|
||||
.path
|
||||
let mut paths = cli.paths.into_iter();
|
||||
let mut pwd = paths
|
||||
.next()
|
||||
.map(|p| if p.is_relative() { basedir.join(p) } else { p })
|
||||
.unwrap_or_else(|| basedir.clone());
|
||||
let mut focused_path = None;
|
||||
|
||||
if pwd.is_file() {
|
||||
if cli.force_focus || pwd.is_file() {
|
||||
focused_path = pwd.file_name().map(|p| p.into());
|
||||
pwd = pwd.parent().map(|p| p.into()).unwrap_or(basedir);
|
||||
}
|
||||
@ -142,7 +143,7 @@ impl Runner {
|
||||
extra_config_files: cli.extra_config,
|
||||
on_load: cli.on_load,
|
||||
read_only: cli.read_only,
|
||||
select: cli.select,
|
||||
select: paths.collect(),
|
||||
})
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user