aboutsummaryrefslogtreecommitdiff
path: root/crates/dinggerd/src/integrations.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/dinggerd/src/integrations.rs')
-rw-r--r--crates/dinggerd/src/integrations.rs41
1 files changed, 40 insertions, 1 deletions
diff --git a/crates/dinggerd/src/integrations.rs b/crates/dinggerd/src/integrations.rs
index a6378d1..d7cbd34 100644
--- a/crates/dinggerd/src/integrations.rs
+++ b/crates/dinggerd/src/integrations.rs
@@ -18,8 +18,47 @@ fn pi_extension_dir() -> Result<PathBuf, String> {
Ok(base.join("extensions"))
}
-/// Install the integration for one agent. Only pi has an integration today.
+/// zsh hook: records the command line running in each tmux pane exactly as
+/// typed (aliases, pipes, quoting), for restore to retype.
+const ZSH_HOOK: &str = r#"# installed by dingger; `dingger install zsh` overwrites this file.
+#
+# Records the command line running in this tmux pane, as typed, in the pane
+# option @dingger_cmd, so `dingger restore` can type it again (without
+# running it) after a crash or shutdown.
+if [[ -n $TMUX_PANE ]]; then
+ _dingger_preexec() { command tmux set-option -p -t "$TMUX_PANE" @dingger_cmd "$1" 2>/dev/null &! }
+ _dingger_precmd() { command tmux set-option -p -u -t "$TMUX_PANE" @dingger_cmd 2>/dev/null &! }
+ autoload -Uz add-zsh-hook
+ add-zsh-hook preexec _dingger_preexec
+ add-zsh-hook precmd _dingger_precmd
+fi
+"#;
+
+fn config_dir() -> Result<PathBuf, String> {
+ std::env::var_os("DINGGER_CONFIG_DIR")
+ .map(PathBuf::from)
+ .or_else(|| std::env::var_os("HOME").map(|home| PathBuf::from(home).join(".config").join("dingger")))
+ .ok_or_else(|| "cannot determine the config dir (no HOME)".to_string())
+}
+
+fn install_zsh() -> Result<(), String> {
+ let dir = config_dir()?;
+ std::fs::create_dir_all(&dir).map_err(|err| format!("mkdir failed: {err}"))?;
+ let path = dir.join("dingger.zsh");
+ std::fs::write(&path, ZSH_HOOK).map_err(|err| format!("write failed: {err}"))?;
+ println!(
+ "installed {}\nadd this line to your .zshrc (dingger does not edit it):\n\n [[ -r {0} ]] && source {0}\n",
+ path.display()
+ );
+ Ok(())
+}
+
+/// Install an integration: an agent's state hooks, or `zsh` for retyping
+/// command lines on restore.
pub fn install(agent: &str) -> Result<(), String> {
+ if agent == "zsh" {
+ return install_zsh();
+ }
let parsed = detect_core::parse_agent_label(agent)
.ok_or_else(|| format!("unknown agent: {agent}"))?;
match parsed {