1use {
3 super::*,
4 crate::{
5 app::*,
6 browser::BrowserState,
7 command::TriggerType,
8 display::Screen,
9 path::{
10 self,
11 PathAnchor,
12 },
13 pattern::InputPattern,
14 preview::PreviewState,
15 task_sync::Dam,
16 tree::TreeOptions,
17 },
18 std::path::{
19 Path,
20 PathBuf,
21 },
22};
23
24pub fn on_path(
25 path: PathBuf,
26 screen: Screen,
27 tree_options: TreeOptions,
28 in_new_panel: bool,
29 con: &AppContext,
30) -> CmdResult {
31 if in_new_panel {
32 new_panel_on_path(
33 path,
34 screen,
35 tree_options,
36 PanelPurpose::None,
37 con,
38 HDir::Right,
39 )
40 } else {
41 new_state_on_path(path, screen, tree_options, con)
42 }
43}
44
45pub fn new_state_on_path(
46 path: PathBuf,
47 screen: Screen,
48 tree_options: TreeOptions,
49 con: &AppContext,
50) -> CmdResult {
51 let path = path::closest_dir(&path);
52 CmdResult::from_optional_browser_state(
53 BrowserState::new(path, tree_options, screen, con, &Dam::unlimited()),
54 None,
55 false,
56 )
57}
58
59#[allow(unused_mut)]
60pub fn new_panel_on_path(
61 mut path: PathBuf,
62 screen: Screen,
63 mut tree_options: TreeOptions,
64 purpose: PanelPurpose,
65 con: &AppContext,
66 direction: HDir,
67) -> CmdResult {
68 #[cfg(not(windows))]
69 if let Ok(canonic) = std::fs::canonicalize(&path) {
72 path = canonic;
73 }
76 if purpose.is_preview() {
77 let pattern = tree_options.pattern.tree_to_preview();
78 CmdResult::NewPanel {
79 state: Box::new(PreviewState::new(path, pattern, None, tree_options, con)),
80 purpose,
81 direction,
82 }
83 } else {
84 let path = path::closest_dir(&path);
85 tree_options.pattern = InputPattern::none();
88 match BrowserState::new(path, tree_options, screen, con, &Dam::unlimited()) {
89 Ok(os) => CmdResult::NewPanel {
90 state: Box::new(os),
91 purpose,
92 direction,
93 },
94 Err(e) => CmdResult::DisplayError(e.to_string()),
95 }
96 }
97}
98
99fn path_from_input(
105 verb: &Verb,
106 internal_exec: &InternalExecution,
107 base_path: &Path, input_arg: Option<&String>,
109 app_state: &AppState,
110 con: &AppContext,
111) -> PathBuf {
112 match (input_arg, internal_exec.arg.as_ref()) {
113 (Some(input_arg), Some(verb_arg)) => {
114 let path_builder = ExecutionBuilder::with_invocation(
122 verb.invocation_parser.as_ref(),
123 SelInfo::from_path(base_path),
124 app_state,
125 Some(input_arg),
126 );
127 path_builder.path(verb_arg, con)
128 }
129 (Some(input_arg), None) => {
130 path::path_from(base_path, PathAnchor::Unspecified, input_arg)
135 }
136 (None, Some(verb_arg)) => {
137 let path_builder = ExecutionBuilder::with_invocation(
145 verb.invocation_parser.as_ref(),
146 SelInfo::from_path(base_path),
147 app_state,
148 None,
149 );
150 path_builder.path(verb_arg, con)
151 }
152 (None, None) => {
153 base_path.to_path_buf()
156 }
157 }
158}
159
160pub fn get_status_markdown(
161 verb: &Verb,
162 internal_exec: &InternalExecution,
163 sel_info: SelInfo<'_>,
164 invocation: &VerbInvocation,
165 app_state: &AppState,
166 con: &AppContext,
167) -> String {
168 let base_path = sel_info.one_path().unwrap_or(&app_state.root);
169 let path = path_from_input(
170 verb,
171 internal_exec,
172 base_path,
173 invocation.args.as_ref(),
174 app_state,
175 con,
176 );
177 format!("Hit *enter* to focus `{}`", path.to_string_lossy())
178}
179
180#[allow(clippy::too_many_arguments)]
183pub fn on_internal(
184 internal_exec: &InternalExecution,
185 input_invocation: Option<&VerbInvocation>,
186 trigger_type: TriggerType,
187 selected_path: &Path,
188 is_root_selected: bool,
189 tree_options: TreeOptions,
190 app_state: &AppState,
191 cc: &CmdContext,
192) -> CmdResult {
193 let con = &cc.app.con;
194 let screen = cc.app.screen;
195 let bang = input_invocation
196 .map(|inv| inv.bang)
197 .unwrap_or(internal_exec.bang);
198 let input_arg = input_invocation
199 .as_ref()
200 .and_then(|invocation| invocation.args.as_ref());
201 match trigger_type {
202 TriggerType::Input(verb) => {
203 let path = path_from_input(
204 verb,
205 internal_exec,
206 selected_path,
207 input_arg,
208 app_state,
209 cc.app.con,
210 );
211 on_path(path, screen, tree_options, bang, con)
212 }
213 _ => {
214 if let Some(arg) = &internal_exec.arg {
216 let path_builder = ExecutionBuilder::without_invocation(
222 SelInfo::from_path(selected_path),
223 app_state,
224 );
225 let path = path_builder.path(arg, con);
226 let bang = input_invocation
227 .map(|inv| inv.bang)
228 .unwrap_or(internal_exec.bang);
229 on_path(path, screen, tree_options, bang, con)
230 } else if let Some(input_arg) = input_arg {
231 let base_dir = selected_path.to_string_lossy();
232 let path = path::path_from(&*base_dir, PathAnchor::Unspecified, input_arg);
233 if bang {
234 let arg_type = SelectionType::Any; let purpose = PanelPurpose::ArgEdition { arg_type };
240 new_panel_on_path(path, screen, tree_options, purpose, con, HDir::Right)
241 } else {
242 on_path(path, screen, tree_options, bang, con)
243 }
244 } else {
245 let mut path = selected_path.to_path_buf();
248 if !bang && is_root_selected {
249 if let Some(parent_path) = selected_path.parent() {
252 path = parent_path.to_path_buf();
253 }
254 }
255 on_path(path, screen, tree_options, bang, con)
256 }
257 }
258 }
259}