Skip to content

Commit

Permalink
kitty support
Browse files Browse the repository at this point in the history
  • Loading branch information
eugene-babichenko committed Jun 12, 2024
1 parent d6d770d commit c277f33
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 7 deletions.
22 changes: 22 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,25 @@ Add this line to your `config.fish` (usually `~/.config/fish/config.fish`):

fixit init fish | source

## Teminal emulator/multiplexer setup

### kitty

You can skip this section if you are using tmux inside Kitty. Quick completions
work out of the box with tmux.

This is optional, but without this `fixit` will fall back to just re-running the
command, which is going to be slower.

To make quick completions work, you need to enable [remote
control][kitty-remote]. This is required, because this application uses
`kitty @ get-text` to retrieve the command output. For the best performance and
stability you are advised to set up [shell integration][kitty-sh-i].

### Other software

You do not need any additional setup.

## Usage

Having a command that broke? Just type `fix`.
Expand Down Expand Up @@ -129,3 +148,6 @@ straightforward without editing shell configuration files.
[rust]: https://www.rust-lang.org/tools/install
[env-logger]:
https://docs.rs/env_logger/latest/env_logger/index.html#enabling-logging
[kitty-remote]:
https://sw.kovidgoyal.net/kitty/conf/#opt-kitty.allow_remote_control
[kitty-sh-i]: https://sw.kovidgoyal.net/kitty/shell-integration/
56 changes: 49 additions & 7 deletions src/fix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,9 @@ impl Cmd {
} else if let Some(output) = get_text_wezterm(&self.cmd, self.quick.depth) {
log::debug!("got output from wezterm");
Some(output)
} else if let Some(output) = get_text_kitty(&self.cmd, self.quick.depth) {
log::debug!("got output from kitty");
Some(output)
} else {
None
}
Expand Down Expand Up @@ -183,8 +186,8 @@ fn get_text_rerun(cmd: &str) -> Result<Option<(String, String)>, Error> {
return Ok(None);
}

let stderr = String::from_utf8(output.stderr)?;
let stdout = String::from_utf8(output.stdout)?;
let stderr = stdout_to_string(output.stderr)?;
let stdout = stdout_to_string(output.stdout)?;

log::debug!("command stderr: {}", stderr);
log::debug!("command stdout: {}", stdout);
Expand All @@ -209,7 +212,7 @@ fn get_text_wezterm(cmd: &str, depth: usize) -> Option<String> {
return None;
}

find_command_outut(cmd, output.stdout)
find_command_output(cmd, output.stdout, depth)
}

fn get_text_tmux(cmd: &str, depth: usize) -> Option<String> {
Expand All @@ -227,12 +230,50 @@ fn get_text_tmux(cmd: &str, depth: usize) -> Option<String> {
return None;
}

find_command_outut(cmd, output.stdout)
find_command_output(cmd, output.stdout, depth)
}

fn get_text_kitty(cmd: &str, depth: usize) -> Option<String> {
if env::var("TERM") != Ok("xterm-kitty".to_string())
&& env::var("KITTY_INSTALLATION_DIR").is_err()
{
return None;
}

log::debug!("getting the command output from kitty");

let shell_integration = env::var("KITTY_SHELL_INTEGRATION").is_ok();
let extent = if shell_integration {
"last_cmd_output"
} else {
// TODO find a way to limit number of lines to `depth`
"all"
};

let output = Command::new("kitty")
.args(["@", "get-text", "--extent", extent])
.output()
.map_err(|e| log::error!("failed to get output from kitty: {e}"))
.ok()?;

if !output.status.success() {
return None;
}

if shell_integration {
stdout_to_string(output.stdout).ok()
} else {
find_command_output(cmd, output.stdout, depth)
}
}

fn stdout_to_string(stdout: Vec<u8>) -> Result<String, Error> {
String::from_utf8(stdout).map_err(Into::into)
}

fn find_command_outut(cmd: &str, stdout: Vec<u8>) -> Option<String> {
let stdout = String::from_utf8(stdout)
.map_err(|e| log::error!("failed to stringify output from WezTerm: {e}"))
fn find_command_output(cmd: &str, stdout: Vec<u8>, depth: usize) -> Option<String> {
let stdout = stdout_to_string(stdout)
.map_err(|e| log::debug!("failed to stringify the command output: {e}"))
.ok()?;

if !stdout.contains(cmd) {
Expand All @@ -250,6 +291,7 @@ fn find_command_outut(cmd: &str, stdout: Vec<u8>) -> Option<String> {
let mut res: Vec<&str> = stdout
.lines()
.rev()
.take(depth)
.take_while(|s| !s.ends_with(cmd) || s.ends_with(&[": ", cmd].concat()))
.collect();
res.reverse();
Expand Down

0 comments on commit c277f33

Please sign in to comment.