added autocmd hooks for screensaver commands
added a landing page for the help command
This commit is contained in:
@@ -8,6 +8,33 @@ use crate::parse::{Node, Redir, RedirType};
|
||||
use crate::prelude::*;
|
||||
use crate::state::AutoCmd;
|
||||
|
||||
#[macro_export]
|
||||
/// Defines a two-way mapping between an enum and its string representation, implementing both Display and FromStr.
|
||||
macro_rules! two_way_display {
|
||||
($name:ident, $($member:ident <=> $val:expr;)*) => {
|
||||
impl Display for $name {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
$(Self::$member => write!(f, $val),)*
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for $name {
|
||||
type Err = ShErr;
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
match s {
|
||||
$($val => Ok(Self::$member),)*
|
||||
_ => Err(ShErr::simple(
|
||||
ShErrKind::ParseErr,
|
||||
format!("Invalid {} kind: {}",stringify!($name),s),
|
||||
)),
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
pub trait VecDequeExt<T> {
|
||||
fn to_vec(self) -> Vec<T>;
|
||||
}
|
||||
|
||||
11
src/main.rs
11
src/main.rs
@@ -329,14 +329,21 @@ fn shed_interactive(args: ShedArgs) -> ShResult<()> {
|
||||
Ok(0) => {
|
||||
// We timed out.
|
||||
if let Some(cmd) = exec_if_timeout {
|
||||
let prepared = ReadlineEvent::Line(cmd);
|
||||
let prepared = ReadlineEvent::Line(cmd.clone());
|
||||
let saved_hist_opt = read_shopts(|o| o.core.auto_hist);
|
||||
let _guard = scopeguard::guard(saved_hist_opt, |opt| {
|
||||
write_shopts(|o| o.core.auto_hist = opt);
|
||||
});
|
||||
write_shopts(|o| o.core.auto_hist = false); // don't save screensaver command to history
|
||||
let pre_cmds = read_logic(|l| l.get_autocmds(AutoCmdKind::OnScreensaverExec));
|
||||
pre_cmds.exec_with(&cmd);
|
||||
|
||||
match handle_readline_event(&mut readline, Ok(prepared))? {
|
||||
let res = handle_readline_event(&mut readline, Ok(prepared))?;
|
||||
|
||||
let post_cmds = read_logic(|l| l.get_autocmds(AutoCmdKind::OnScreensaverReturn));
|
||||
post_cmds.exec_with(&cmd);
|
||||
|
||||
match res {
|
||||
true => return Ok(()),
|
||||
false => continue,
|
||||
}
|
||||
|
||||
@@ -509,6 +509,12 @@ pub enum LoopKind {
|
||||
Until,
|
||||
}
|
||||
|
||||
crate::two_way_display!(LoopKind,
|
||||
While <=> "while";
|
||||
Until <=> "until";
|
||||
);
|
||||
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum TestCase {
|
||||
Unary {
|
||||
@@ -638,29 +644,6 @@ impl TestCaseBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for LoopKind {
|
||||
type Err = ShErr;
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
match s {
|
||||
"while" => Ok(Self::While),
|
||||
"until" => Ok(Self::Until),
|
||||
_ => Err(ShErr::simple(
|
||||
ShErrKind::ParseErr,
|
||||
format!("Invalid loop kind: {s}"),
|
||||
)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for LoopKind {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
LoopKind::While => write!(f, "while"),
|
||||
LoopKind::Until => write!(f, "until"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum AssignKind {
|
||||
Eq,
|
||||
|
||||
@@ -925,7 +925,7 @@ impl LineBuf {
|
||||
}
|
||||
Direction::Backward => {
|
||||
let slice = self.line_to_cursor();
|
||||
for (i, gr) in slice.iter().rev().enumerate().skip(1) {
|
||||
for (i, gr) in slice.iter().rev().enumerate() {
|
||||
if gr == char {
|
||||
match dest {
|
||||
Dest::On => return -(i as isize) - 1,
|
||||
|
||||
72
src/state.rs
72
src/state.rs
@@ -631,59 +631,31 @@ pub enum AutoCmdKind {
|
||||
OnCompletionStart,
|
||||
OnCompletionCancel,
|
||||
OnCompletionSelect,
|
||||
OnScreensaverExec,
|
||||
OnScreensaverReturn,
|
||||
OnExit,
|
||||
}
|
||||
|
||||
impl Display for AutoCmdKind {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
Self::PreCmd => write!(f, "pre-cmd"),
|
||||
Self::PostCmd => write!(f, "post-cmd"),
|
||||
Self::PreChangeDir => write!(f, "pre-change-dir"),
|
||||
Self::PostChangeDir => write!(f, "post-change-dir"),
|
||||
Self::OnJobFinish => write!(f, "on-job-finish"),
|
||||
Self::PrePrompt => write!(f, "pre-prompt"),
|
||||
Self::PostPrompt => write!(f, "post-prompt"),
|
||||
Self::PreModeChange => write!(f, "pre-mode-change"),
|
||||
Self::PostModeChange => write!(f, "post-mode-change"),
|
||||
Self::OnHistoryOpen => write!(f, "on-history-open"),
|
||||
Self::OnHistoryClose => write!(f, "on-history-close"),
|
||||
Self::OnHistorySelect => write!(f, "on-history-select"),
|
||||
Self::OnCompletionStart => write!(f, "on-completion-start"),
|
||||
Self::OnCompletionCancel => write!(f, "on-completion-cancel"),
|
||||
Self::OnCompletionSelect => write!(f, "on-completion-select"),
|
||||
Self::OnExit => write!(f, "on-exit"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for AutoCmdKind {
|
||||
type Err = ShErr;
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
match s {
|
||||
"pre-cmd" => Ok(Self::PreCmd),
|
||||
"post-cmd" => Ok(Self::PostCmd),
|
||||
"pre-change-dir" => Ok(Self::PreChangeDir),
|
||||
"post-change-dir" => Ok(Self::PostChangeDir),
|
||||
"on-job-finish" => Ok(Self::OnJobFinish),
|
||||
"pre-prompt" => Ok(Self::PrePrompt),
|
||||
"post-prompt" => Ok(Self::PostPrompt),
|
||||
"pre-mode-change" => Ok(Self::PreModeChange),
|
||||
"post-mode-change" => Ok(Self::PostModeChange),
|
||||
"on-history-open" => Ok(Self::OnHistoryOpen),
|
||||
"on-history-close" => Ok(Self::OnHistoryClose),
|
||||
"on-history-select" => Ok(Self::OnHistorySelect),
|
||||
"on-completion-start" => Ok(Self::OnCompletionStart),
|
||||
"on-completion-cancel" => Ok(Self::OnCompletionCancel),
|
||||
"on-completion-select" => Ok(Self::OnCompletionSelect),
|
||||
"on-exit" => Ok(Self::OnExit),
|
||||
_ => Err(ShErr::simple(
|
||||
ShErrKind::ParseErr,
|
||||
format!("Invalid autocmd kind: {}", s),
|
||||
)),
|
||||
}
|
||||
}
|
||||
}
|
||||
crate::two_way_display!(AutoCmdKind,
|
||||
PreCmd <=> "pre-cmd";
|
||||
PostCmd <=> "post-cmd";
|
||||
PreChangeDir <=> "pre-change-dir";
|
||||
PostChangeDir <=> "post-change-dir";
|
||||
OnJobFinish <=> "on-job-finish";
|
||||
PrePrompt <=> "pre-prompt";
|
||||
PostPrompt <=> "post-prompt";
|
||||
PreModeChange <=> "pre-mode-change";
|
||||
PostModeChange <=> "post-mode-change";
|
||||
OnHistoryOpen <=> "on-history-open";
|
||||
OnHistoryClose <=> "on-history-close";
|
||||
OnHistorySelect <=> "on-history-select";
|
||||
OnCompletionStart <=> "on-completion-start";
|
||||
OnCompletionCancel <=> "on-completion-cancel";
|
||||
OnCompletionSelect <=> "on-completion-select";
|
||||
OnScreensaverExec <=> "on-screensaver-exec";
|
||||
OnScreensaverReturn <=> "on-screensaver-return";
|
||||
OnExit <=> "on-exit";
|
||||
);
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct AutoCmd {
|
||||
|
||||
Reference in New Issue
Block a user