mirror of
https://github.com/gitui-org/gitui
synced 2026-05-23 17:08:21 +00:00
add cli flag to open files tab with selected file (#2746)
This commit is contained in:
parent
a6d6f31885
commit
ffa6d9e57b
7 changed files with 77 additions and 19 deletions
|
|
@ -19,6 +19,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
* dx: `make check` checks Cargo.toml dependency ordering using `cargo sort` [[@naseschwarz](https://github.com/naseschwarz)]
|
||||
* add `use_selection_fg` to theme file to allow customizing selection foreground color [[@Upsylonbare](https://github.com/Upsylonbare)] ([#2515](https://github.com/gitui-org/gitui/pull/2515))
|
||||
* Add "go to line" command for the blame view [[@andrea-berling](https://github.com/andrea-berling)] ([#2262](https://github.com/extrawurst/gitui/pull/2262))
|
||||
* add `--file` cli flag to open the files tab with the given file already selected [[@laktak](https://github.com/laktak)] ([#2510](https://github.com/gitui-org/gitui/issues/2510))
|
||||
|
||||
### Changed
|
||||
* improve error messages [[@acuteenvy](https://github.com/acuteenvy)] ([#2617](https://github.com/gitui-org/gitui/pull/2617))
|
||||
|
|
|
|||
21
src/app.rs
21
src/app.rs
|
|
@ -1,5 +1,6 @@
|
|||
use crate::{
|
||||
accessors,
|
||||
args::CliArgs,
|
||||
cmdbar::CommandBar,
|
||||
components::{
|
||||
command_pump, event_pump, CommandInfo, Component,
|
||||
|
|
@ -151,13 +152,14 @@ impl App {
|
|||
///
|
||||
#[allow(clippy::too_many_lines)]
|
||||
pub fn new(
|
||||
repo: RepoPathRef,
|
||||
cliargs: CliArgs,
|
||||
sender_git: Sender<AsyncGitNotification>,
|
||||
sender_app: Sender<AsyncAppNotification>,
|
||||
input: Input,
|
||||
theme: Theme,
|
||||
key_config: KeyConfig,
|
||||
) -> Result<Self> {
|
||||
let repo = RefCell::new(cliargs.repo_path.clone());
|
||||
log::trace!("open repo at: {:?}", &repo);
|
||||
|
||||
let repo_path_text =
|
||||
|
|
@ -173,7 +175,20 @@ impl App {
|
|||
sender_app,
|
||||
};
|
||||
|
||||
let tab = env.options.borrow().current_tab();
|
||||
let mut select_file: Option<PathBuf> = None;
|
||||
let tab = if let Some(file) = cliargs.select_file {
|
||||
// convert to relative git path
|
||||
if let Ok(abs) = file.canonicalize() {
|
||||
if let Ok(path) = abs.strip_prefix(
|
||||
env.repo.borrow().gitpath().canonicalize()?,
|
||||
) {
|
||||
select_file = Some(Path::new(".").join(path));
|
||||
}
|
||||
}
|
||||
2
|
||||
} else {
|
||||
env.options.borrow().current_tab()
|
||||
};
|
||||
|
||||
let mut app = Self {
|
||||
input,
|
||||
|
|
@ -218,7 +233,7 @@ impl App {
|
|||
status_tab: Status::new(&env),
|
||||
stashing_tab: Stashing::new(&env),
|
||||
stashlist_tab: StashList::new(&env),
|
||||
files_tab: FilesTab::new(&env),
|
||||
files_tab: FilesTab::new(&env, select_file),
|
||||
goto_line_popup: GotoLinePopup::new(&env),
|
||||
tab: 0,
|
||||
queue: env.queue,
|
||||
|
|
|
|||
15
src/args.rs
15
src/args.rs
|
|
@ -17,13 +17,16 @@ const LOG_FILE_FLAG_ID: &str = "logfile";
|
|||
const LOGGING_FLAG_ID: &str = "logging";
|
||||
const THEME_FLAG_ID: &str = "theme";
|
||||
const WORKDIR_FLAG_ID: &str = "workdir";
|
||||
const FILE_FLAG_ID: &str = "file";
|
||||
const GIT_DIR_FLAG_ID: &str = "directory";
|
||||
const WATCHER_FLAG_ID: &str = "watcher";
|
||||
const DEFAULT_THEME: &str = "theme.ron";
|
||||
const DEFAULT_GIT_DIR: &str = ".";
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct CliArgs {
|
||||
pub theme: PathBuf,
|
||||
pub select_file: Option<PathBuf>,
|
||||
pub repo_path: RepoPath,
|
||||
pub notify_watcher: bool,
|
||||
}
|
||||
|
|
@ -51,6 +54,10 @@ pub fn process_cmdline() -> Result<CliArgs> {
|
|||
PathBuf::from,
|
||||
);
|
||||
|
||||
let select_file = arg_matches
|
||||
.get_one::<String>(FILE_FLAG_ID)
|
||||
.map(PathBuf::from);
|
||||
|
||||
let repo_path = if let Some(w) = workdir {
|
||||
RepoPath::Workdir { gitdir, workdir: w }
|
||||
} else {
|
||||
|
|
@ -75,6 +82,7 @@ pub fn process_cmdline() -> Result<CliArgs> {
|
|||
|
||||
Ok(CliArgs {
|
||||
theme,
|
||||
select_file,
|
||||
repo_path,
|
||||
notify_watcher,
|
||||
})
|
||||
|
|
@ -129,6 +137,13 @@ fn app() -> ClapApp {
|
|||
.long("bugreport")
|
||||
.action(clap::ArgAction::SetTrue),
|
||||
)
|
||||
.arg(
|
||||
Arg::new(FILE_FLAG_ID)
|
||||
.help("Select the file in the file tab")
|
||||
.short('f')
|
||||
.long("file")
|
||||
.num_args(1),
|
||||
)
|
||||
.arg(
|
||||
Arg::new(GIT_DIR_FLAG_ID)
|
||||
.help("Set the git directory")
|
||||
|
|
|
|||
|
|
@ -30,7 +30,10 @@ use ratatui::{
|
|||
Frame,
|
||||
};
|
||||
use std::{borrow::Cow, fmt::Write};
|
||||
use std::{collections::BTreeSet, path::Path};
|
||||
use std::{
|
||||
collections::BTreeSet,
|
||||
path::{Path, PathBuf},
|
||||
};
|
||||
use unicode_truncate::UnicodeTruncateStr;
|
||||
use unicode_width::UnicodeWidthStr;
|
||||
|
||||
|
|
@ -53,11 +56,15 @@ pub struct RevisionFilesComponent {
|
|||
revision: Option<CommitInfo>,
|
||||
focus: Focus,
|
||||
key_config: SharedKeyConfig,
|
||||
select_file: Option<PathBuf>,
|
||||
}
|
||||
|
||||
impl RevisionFilesComponent {
|
||||
///
|
||||
pub fn new(env: &Environment) -> Self {
|
||||
pub fn new(
|
||||
env: &Environment,
|
||||
select_file: Option<PathBuf>,
|
||||
) -> Self {
|
||||
Self {
|
||||
queue: env.queue.clone(),
|
||||
tree: FileTree::default(),
|
||||
|
|
@ -72,6 +79,7 @@ impl RevisionFilesComponent {
|
|||
focus: Focus::Tree,
|
||||
key_config: env.key_config.clone(),
|
||||
repo: env.repo.clone(),
|
||||
select_file,
|
||||
visible: false,
|
||||
}
|
||||
}
|
||||
|
|
@ -134,6 +142,12 @@ impl RevisionFilesComponent {
|
|||
self.tree.collapse_but_root();
|
||||
|
||||
self.files = Some(last);
|
||||
|
||||
let select_file = self.select_file.clone();
|
||||
self.select_file = None;
|
||||
if let Some(file) = select_file {
|
||||
self.find_file(file.as_path());
|
||||
}
|
||||
}
|
||||
} else if let Some(rev) = &self.revision {
|
||||
self.request_files(rev.id);
|
||||
|
|
|
|||
30
src/main.rs
30
src/main.rs
|
|
@ -79,7 +79,10 @@ mod tabs;
|
|||
mod ui;
|
||||
mod watcher;
|
||||
|
||||
use crate::{app::App, args::process_cmdline};
|
||||
use crate::{
|
||||
app::App,
|
||||
args::{process_cmdline, CliArgs},
|
||||
};
|
||||
use anyhow::{anyhow, bail, Result};
|
||||
use app::QuitState;
|
||||
use asyncgit::{
|
||||
|
|
@ -102,7 +105,6 @@ use scopeguard::defer;
|
|||
use scopetime::scope_time;
|
||||
use spinner::Spinner;
|
||||
use std::{
|
||||
cell::RefCell,
|
||||
io::{self, Stdout},
|
||||
panic,
|
||||
path::Path,
|
||||
|
|
@ -180,8 +182,8 @@ fn main() -> Result<()> {
|
|||
|
||||
set_panic_handler()?;
|
||||
|
||||
let mut repo_path = cliargs.repo_path;
|
||||
let mut terminal = start_terminal(io::stdout(), &repo_path)?;
|
||||
let mut terminal =
|
||||
start_terminal(io::stdout(), &cliargs.repo_path)?;
|
||||
let input = Input::new();
|
||||
|
||||
let updater = if cliargs.notify_watcher {
|
||||
|
|
@ -190,10 +192,12 @@ fn main() -> Result<()> {
|
|||
Updater::Ticker
|
||||
};
|
||||
|
||||
let mut args = cliargs;
|
||||
|
||||
loop {
|
||||
let quit_state = run_app(
|
||||
app_start,
|
||||
repo_path.clone(),
|
||||
args.clone(),
|
||||
theme.clone(),
|
||||
key_config.clone(),
|
||||
&input,
|
||||
|
|
@ -203,7 +207,12 @@ fn main() -> Result<()> {
|
|||
|
||||
match quit_state {
|
||||
QuitState::OpenSubmodule(p) => {
|
||||
repo_path = p;
|
||||
args = CliArgs {
|
||||
repo_path: p,
|
||||
select_file: None,
|
||||
theme: args.theme,
|
||||
notify_watcher: args.notify_watcher,
|
||||
}
|
||||
}
|
||||
_ => break,
|
||||
}
|
||||
|
|
@ -214,7 +223,7 @@ fn main() -> Result<()> {
|
|||
|
||||
fn run_app(
|
||||
app_start: Instant,
|
||||
repo: RepoPath,
|
||||
cliargs: CliArgs,
|
||||
theme: Theme,
|
||||
key_config: KeyConfig,
|
||||
input: &Input,
|
||||
|
|
@ -228,8 +237,9 @@ fn run_app(
|
|||
|
||||
let (rx_ticker, rx_watcher) = match updater {
|
||||
Updater::NotifyWatcher => {
|
||||
let repo_watcher =
|
||||
RepoWatcher::new(repo_work_dir(&repo)?.as_str());
|
||||
let repo_watcher = RepoWatcher::new(
|
||||
repo_work_dir(&cliargs.repo_path)?.as_str(),
|
||||
);
|
||||
|
||||
(never(), repo_watcher.receiver())
|
||||
}
|
||||
|
|
@ -239,7 +249,7 @@ fn run_app(
|
|||
let spinner_ticker = tick(SPINNER_INTERVAL);
|
||||
|
||||
let mut app = App::new(
|
||||
RefCell::new(repo),
|
||||
cliargs,
|
||||
tx_git,
|
||||
tx_app,
|
||||
input.clone(),
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ impl RevisionFilesPopup {
|
|||
///
|
||||
pub fn new(env: &Environment) -> Self {
|
||||
Self {
|
||||
files: RevisionFilesComponent::new(env),
|
||||
files: RevisionFilesComponent::new(env, None),
|
||||
visible: false,
|
||||
key_config: env.key_config.clone(),
|
||||
open_request: None,
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use std::path::Path;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use crate::{
|
||||
app::Environment,
|
||||
|
|
@ -19,10 +19,13 @@ pub struct FilesTab {
|
|||
|
||||
impl FilesTab {
|
||||
///
|
||||
pub fn new(env: &Environment) -> Self {
|
||||
pub fn new(
|
||||
env: &Environment,
|
||||
select_file: Option<PathBuf>,
|
||||
) -> Self {
|
||||
Self {
|
||||
visible: false,
|
||||
files: RevisionFilesComponent::new(env),
|
||||
files: RevisionFilesComponent::new(env, select_file),
|
||||
repo: env.repo.clone(),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue