Skip to content

Commit

Permalink
:write_output & :clear_output, --verb_output
Browse files Browse the repository at this point in the history
Fix: #825
  • Loading branch information
Canop committed Feb 11, 2024
1 parent d1dba3c commit ea07ced
Show file tree
Hide file tree
Showing 16 changed files with 80 additions and 9 deletions.
41 changes: 39 additions & 2 deletions src/app/panel_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,11 @@ pub trait PanelState {
/// The invocation comes from the input and may be related
/// to a different verb (the verb may have been triggered
/// by a key shortcut)
#[allow(clippy::too_many_arguments)]
fn on_internal(
&mut self,
w: &mut W,
invocation_parser: Option<&InvocationParser>,
internal_exec: &InternalExecution,
input_invocation: Option<&VerbInvocation>,
trigger_type: TriggerType,
Expand All @@ -92,9 +94,11 @@ pub trait PanelState {
/// a generic implementation of on_internal which may be
/// called by states when they don't have a specific
/// behavior to execute
#[allow(clippy::too_many_arguments)]
fn on_internal_generic(
&mut self,
_w: &mut W,
invocation_parser: Option<&InvocationParser>,
internal_exec: &InternalExecution,
input_invocation: Option<&VerbInvocation>,
_trigger_type: TriggerType,
Expand Down Expand Up @@ -571,6 +575,37 @@ pub trait PanelState {
Internal::print_relative_path => print::print_relative_paths(self.sel_info(app_state), con)?,
Internal::refresh => CmdResult::RefreshState { clear_cache: true },
Internal::quit => CmdResult::Quit,
Internal::clear_output => {
verb_clear_output(con)
.unwrap_or_else(|e| CmdResult::DisplayError(format!("{e}")))
}
Internal::write_output => {
let sel_info = self.sel_info(app_state);
let exec_builder = match input_invocation {
Some(inv) => {
ExecutionStringBuilder::with_invocation(
invocation_parser,
sel_info,
app_state,
inv.args.as_ref(),
)
}
None => {
ExecutionStringBuilder::without_invocation(sel_info, app_state)
}
};
if let Some(pattern) = internal_exec.arg.as_ref() {
let line = exec_builder.string(pattern);
verb_write(con, &line)?;
} else {
let line = input_invocation
.and_then(|inv| inv.args.as_ref())
.map(|s| s.as_str())
.unwrap_or("");
verb_write(con, line)?;
}
CmdResult::Keep
}
_ => CmdResult::Keep,
})
}
Expand Down Expand Up @@ -653,6 +688,7 @@ pub trait PanelState {
VerbExecution::Internal(internal_exec) => {
self.on_internal(
w,
verb.invocation_parser.as_ref(),
internal_exec,
invocation,
trigger_type,
Expand Down Expand Up @@ -700,7 +736,7 @@ pub trait PanelState {
}
}
let exec_builder = ExecutionStringBuilder::with_invocation(
&verb.invocation_parser,
verb.invocation_parser.as_ref(),
sel_info,
app_state,
if let Some(inv) = invocation {
Expand Down Expand Up @@ -729,7 +765,7 @@ pub trait PanelState {
return Ok(CmdResult::error("sequences can't be executed on multiple selections"));
}
let exec_builder = ExecutionStringBuilder::with_invocation(
&verb.invocation_parser,
verb.invocation_parser.as_ref(),
sel_info,
app_state,
if let Some(inv) = invocation {
Expand Down Expand Up @@ -782,6 +818,7 @@ pub trait PanelState {
input_invocation,
} => self.on_internal(
w,
None,
&InternalExecution::from_internal(*internal),
input_invocation.as_ref(),
TriggerType::Other,
Expand Down
2 changes: 2 additions & 0 deletions src/browser/browser_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,7 @@ impl PanelState for BrowserState {
fn on_internal(
&mut self,
w: &mut W,
invocation_parser: Option<&InvocationParser>,
internal_exec: &InternalExecution,
input_invocation: Option<&VerbInvocation>,
trigger_type: TriggerType,
Expand Down Expand Up @@ -612,6 +613,7 @@ impl PanelState for BrowserState {
Internal::quit => CmdResult::Quit,
_ => self.on_internal_generic(
w,
invocation_parser,
internal_exec,
input_invocation,
trigger_type,
Expand Down
4 changes: 4 additions & 0 deletions src/cli/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,10 @@ pub struct Args {
#[arg(long, value_name = "path")]
pub outcmd: Option<PathBuf>,

/// An optional path where to write when a verb uses `:write_output`
#[arg(long, value_name = "verb-output")]
pub verb_output: Option<PathBuf>,

/// Semicolon separated commands to execute
#[arg(short, long, value_name = "cmd")]
pub cmd: Option<String>,
Expand Down
1 change: 1 addition & 0 deletions src/cli/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,7 @@ pub fn run() -> Result<Option<Launchable>, ProgramError> {
w.queue(EnableMouseCapture)?;
}
let r = app.run(&mut w, &mut context, &config);
w.flush()?;
if context.capture_mouse {
w.queue(DisableMouseCapture)?;
}
Expand Down
2 changes: 2 additions & 0 deletions src/filesystems/filesystems_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -474,6 +474,7 @@ impl PanelState for FilesystemState {
fn on_internal(
&mut self,
w: &mut W,
invocation_parser: Option<&InvocationParser>,
internal_exec: &InternalExecution,
input_invocation: Option<&VerbInvocation>,
trigger_type: TriggerType,
Expand Down Expand Up @@ -578,6 +579,7 @@ impl PanelState for FilesystemState {
open_leave => CmdResult::PopStateAndReapply,
_ => self.on_internal_generic(
w,
invocation_parser,
internal_exec,
input_invocation,
trigger_type,
Expand Down
2 changes: 2 additions & 0 deletions src/help/help_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,7 @@ impl PanelState for HelpState {
fn on_internal(
&mut self,
w: &mut W,
invocation_parser: Option<&InvocationParser>,
internal_exec: &InternalExecution,
input_invocation: Option<&VerbInvocation>,
trigger_type: TriggerType,
Expand Down Expand Up @@ -260,6 +261,7 @@ impl PanelState for HelpState {
}
_ => self.on_internal_generic(
w,
invocation_parser,
internal_exec,
input_invocation,
trigger_type,
Expand Down
2 changes: 2 additions & 0 deletions src/preview/preview_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,7 @@ impl PanelState for PreviewState {
fn on_internal(
&mut self,
w: &mut W,
invocation_parser: Option<&InvocationParser>,
internal_exec: &InternalExecution,
input_invocation: Option<&VerbInvocation>,
trigger_type: TriggerType,
Expand Down Expand Up @@ -397,6 +398,7 @@ impl PanelState for PreviewState {
Internal::preview_binary => self.set_mode(PreviewMode::Hex, con),
_ => self.on_internal_generic(
w,
invocation_parser,
internal_exec,
input_invocation,
trigger_type,
Expand Down
1 change: 0 additions & 1 deletion src/shell_install/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ pub fn file_contains_line(path: &Path, searched_line: &str) -> Result<bool, Shel

pub fn append_to_file<S: AsRef<str>>(path: &Path, content: S) -> Result<(), ShellInstallError> {
let mut shellrc = OpenOptions::new()
.write(true)
.append(true)
.open(path)
.context(&|| format!("opening {path:?} for append"))?;
Expand Down
2 changes: 2 additions & 0 deletions src/stage/stage_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -443,6 +443,7 @@ impl PanelState for StageState {
fn on_internal(
&mut self,
w: &mut W,
invocation_parser: Option<&InvocationParser>,
internal_exec: &InternalExecution,
input_invocation: Option<&VerbInvocation>,
trigger_type: TriggerType,
Expand Down Expand Up @@ -505,6 +506,7 @@ impl PanelState for StageState {
}
_ => self.on_internal_generic(
w,
invocation_parser,
internal_exec,
input_invocation,
trigger_type,
Expand Down
15 changes: 13 additions & 2 deletions src/verb/execution_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ impl<'b> ExecutionStringBuilder<'b> {
}
}
pub fn with_invocation(
invocation_parser: &Option<InvocationParser>,
invocation_parser: Option<&InvocationParser>,
sel_info: SelInfo<'b>,
app_state: &'b AppState,
invocation_args: Option<&String>,
Expand Down Expand Up @@ -253,7 +253,18 @@ impl<'b> ExecutionStringBuilder<'b> {
.one_sel()
.map_or(self.root, |sel| sel.path)
}

/// build a raw string, without escapings
pub fn string(
&self,
pattern: &str,
) -> String {
GROUP
.replace_all(
pattern,
|ec: &Captures<'_>| self.get_capture_replacement(ec),
)
.to_string()
}
/// build a path
pub fn path(
&self,
Expand Down
4 changes: 4 additions & 0 deletions src/verb/internal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,8 @@ Internals! {
trash: "move file to system trash" true,
unstage: "remove selection from staging area" true,
up_tree: "focus the parent of the current root" true,
write_output: "write the argument to the --verb-output file" false,
clear_output: "clear the --verb-output file" false,
//restore_pattern: "restore a pattern which was just removed" false,
}

Expand All @@ -161,6 +163,7 @@ impl Internal {
Internal::line_down_no_cycle => r"line_down_no_cycle (?P<count>\d*)?",
Internal::line_up_no_cycle => r"line_up_no_cycle (?P<count>\d*)?",
Internal::set_syntax_theme => r"set_syntax_theme {theme:theme}",
Internal::write_output => r"write_output (?P<line>.*)",
_ => self.name(),
}
}
Expand All @@ -171,6 +174,7 @@ impl Internal {
Internal::line_up => r"line_up {count}",
Internal::line_down_no_cycle => r"line_down_no_cycle {count}",
Internal::line_up_no_cycle => r"line_up_no_cycle {count}",
Internal::write_output => r"write_output {line}",
_ => self.name(),
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/verb/internal_focus.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ fn path_from_input(
// }
// (or that input is useless)
let path_builder = ExecutionStringBuilder::with_invocation(
&verb.invocation_parser,
verb.invocation_parser.as_ref(),
SelInfo::from_path(base_path),
app_state,
Some(input_arg),
Expand All @@ -137,7 +137,7 @@ fn path_from_input(
// state's selection
// (we assume a check before ensured it doesn't need an input)
let path_builder = ExecutionStringBuilder::with_invocation(
&verb.invocation_parser,
verb.invocation_parser.as_ref(),
SelInfo::from_path(base_path),
app_state,
None,
Expand Down
2 changes: 1 addition & 1 deletion src/verb/internal_select.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ fn path_from_input(
// }
// (or that input is useless)
let path_builder = ExecutionStringBuilder::with_invocation(
&verb.invocation_parser,
verb.invocation_parser.as_ref(),
SelInfo::from_path(base_path),
app_state,
Some(input_arg),
Expand Down
2 changes: 2 additions & 0 deletions src/verb/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ mod verb_description;
mod verb_execution;
mod verb_invocation;
mod verb_store;
mod write;

pub use {
arg_def::*,
Expand All @@ -33,6 +34,7 @@ pub use {
verb_execution::VerbExecution,
verb_invocation::*,
verb_store::{PrefixSearchResult, VerbStore},
write::*,
};
use {
lazy_regex::*,
Expand Down
2 changes: 1 addition & 1 deletion src/verb/verb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@ impl Verb {

let builder = || {
ExecutionStringBuilder::with_invocation(
&self.invocation_parser,
self.invocation_parser.as_ref(),
sel_info,
app_state,
invocation.args.as_ref(),
Expand Down
3 changes: 3 additions & 0 deletions src/verb/verb_store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,9 @@ impl VerbStore {
self.add_internal(trash);
self.add_internal(total_search).with_key(key!(ctrl-s));
self.add_internal(up_tree).with_shortcut("up");

self.add_internal(clear_output);
self.add_internal(write_output);
}

fn build_add_internal(
Expand Down

0 comments on commit ea07ced

Please sign in to comment.