use super::*;
use crate::tui::terminal::Tui;
use std::io;
use std::path::Path;
use crate::domain::repo::{self, Repo, RepoKind};
use crate::tui::git_columns::effective_info;
use crate::tui::presentation::github_url;
use crate::util::opener::launch_git_tool;
impl App {
pub(super) fn open_selected(
&mut self,
launch_tool: bool,
) -> Option<RunOutcome> {
let index = self.selected_index()?;
let repo = self.service.get(index)?.clone();
if let Err(error) = self.service.mark_used(index) {
self.set_status(format!("could not record usage: {error}"));
}
match repo.kind {
RepoKind::Git if launch_tool => {
self.write_selected(&repo.path);
Some(RunOutcome::LaunchGitTool(repo.path))
}
RepoKind::Git => {
self.write_selected(&repo.path);
Some(RunOutcome::Jumped)
}
RepoKind::Path => self.open_path_entry(repo, launch_tool),
}
}
pub(super) fn open_git_inline(&mut self) -> Option<RunOutcome> {
let index = self.selected_index()?;
let repo = self.service.get(index)?.clone();
if repo.kind != RepoKind::Git {
self.set_status("not a git repo");
return None;
}
if let Err(error) = self.service.mark_used(index) {
self.set_status(format!("could not record usage: {error}"));
}
Some(RunOutcome::LaunchGitToolInline(repo.path))
}
pub(super) fn run_git_inline(
&mut self,
tui: &mut Tui,
dir: &Path,
) -> io::Result<()> {
let Some(program) = self.config.git_program.clone() else {
self.set_status("no git_program configured");
return Ok(());
};
tui.suspend(|| {
if let Err(error) = launch_git_tool(&program, dir) {
log::error!("could not launch {program}: {error}");
}
})?;
if !self.config.example_mode {
self.refresh_paths(vec![dir.to_path_buf()], false, false);
}
Ok(())
}
pub(super) fn open_path_entry(
&mut self,
repo: Repo,
launch_tool: bool,
) -> Option<RunOutcome> {
let class =
repo::classify_path(&repo.path, &self.config.editor_extensions);
if class == repo::PathClass::Folder {
self.write_selected(&repo.path);
return Some(RunOutcome::Jumped);
}
if !launch_tool {
let dir = repo
.path
.parent()
.map_or_else(|| repo.path.clone(), Path::to_path_buf);
self.write_selected(&dir);
return Some(RunOutcome::Jumped);
}
match class {
repo::PathClass::TextFile => Some(RunOutcome::OpenFile(repo.path)),
_ => Some(RunOutcome::OpenWith(repo.path)),
}
}
pub(super) fn force_open_with(&mut self) -> Option<RunOutcome> {
let index = self.selected_index()?;
let repo = self.service.get(index)?.clone();
if let Err(error) = self.service.mark_used(index) {
self.set_status(format!("could not record usage: {error}"));
}
Some(RunOutcome::OpenWith(repo.path))
}
pub(super) fn write_selected(&mut self, path: &std::path::Path) {
if let Err(error) = self.service.write_selected(path) {
self.set_status(format!("could not write selected path: {error}"));
}
}
pub(super) fn copy_path(&mut self) {
let paths = self.target_paths();
if paths.is_empty() {
return;
}
let count = paths.len();
let text = paths.join("\n");
match crate::util::clipboard::copy(&text) {
Ok(()) => self.set_status(if count == 1 {
"copied path to clipboard".to_string()
} else {
format!("copied {count} paths to clipboard")
}),
Err(error) => self.set_status(format!("copy failed: {error}")),
}
}
pub(super) fn open_on_github(&mut self) {
let targets = self.targets();
let urls: Vec<String> = targets
.iter()
.filter_map(|&index| self.github_url_for(index))
.collect();
if urls.is_empty() {
self.set_status("no GitHub remote");
return;
}
let mut opened = 0;
for url in &urls {
match crate::util::opener::open_url(url) {
Ok(_) => opened += 1,
Err(error) => {
self.set_status(format!("could not open browser: {error}"));
}
}
}
if opened == 0 {
return;
}
let skipped = targets.len() - urls.len();
if opened == 1 && skipped == 0 {
self.set_status(format!("opening {}", urls[0]));
} else if skipped == 0 {
self.set_status(format!("opening {opened} GitHub pages"));
} else {
self.set_status(format!(
"opening {opened} GitHub pages ({skipped} skipped)"
));
}
}
pub(super) fn github_url_for(&self, index: usize) -> Option<String> {
let repo = self.service.get(index)?;
let info = effective_info(repo, self.config.example_mode);
let name = info.and_then(|info| info.github_repo_name.clone())?;
github_url(&name, self.config.github_username.as_deref())
}
}