Skip to content

Commit

Permalink
Add xonsh support (#1375)
Browse files Browse the repository at this point in the history
* Add basic xonsh support

* Add init xonsh command

* Add Xonsh install instructions in docs

* Add xonsh ctrl-R search

* update xonsh script and instructions

Summary of changes:
* Added duration to postcommand hook
* Switched main search operation to use `subproccess.run()` rather than running as an xonsh shell command - this a) allows us to capture stderr without needing a temporary file and b) avoids a weird broken-buffer state that results from running a fullscreen TUI and then programmatically editing the buffer
* Added support for immediately executing chosen command via `__atuin_accept__:` (like bash/zsh/fish)

* strip newline from command before sending to atuin

* Add basic xonsh support

* Add init xonsh command

* Add xonsh ctrl-R search

* Remove advanced-install guide (was accidentally re-added during rebase)

* Clean up

Xonsh doesn't import private functions into the local namespace when sourcing a file

* Add xonsh ro readme

* Respect ATUIN_NOBIND

* Format with black, and improve PEP8 compliance

* Add up search

* Format rust code

---------

Co-authored-by: Joseph Montanaro <jfmonty2@gmail.com>
  • Loading branch information
Matthieu-LAURENT39 and jfmontanaro authored Jan 29, 2024
1 parent 0faf414 commit c56f8ff
Show file tree
Hide file tree
Showing 5 changed files with 105 additions and 1 deletion.
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ I wanted to. And I **really** don't want to.
- bash
- fish
- nushell
- xonsh

## Community

Expand Down Expand Up @@ -327,6 +328,14 @@ Add to `config.nu`:
source ~/.local/share/atuin/init.nu
```

### Xonsh

Add
```
execx($(atuin init xonsh))
```
to the end of your `~/.xonshrc`

# Contributors

<a href="https://github.com/atuinsh/atuin/graphs/contributors">
Expand Down
5 changes: 5 additions & 0 deletions atuin-common/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,11 @@ pub fn is_bash() -> bool {
env::var("ATUIN_SHELL_BASH").is_ok()
}

pub fn is_xonsh() -> bool {
// only set on xonsh
env::var("ATUIN_SHELL_XONSH").is_ok()
}

/// Extension trait for anything that can behave like a string to make it easy to escape control
/// characters.
///
Expand Down
4 changes: 3 additions & 1 deletion atuin/src/command/client/search/interactive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -967,7 +967,9 @@ pub async fn history(
match result {
InputAction::Accept(index) if index < results.len() => {
let mut command = results.swap_remove(index).command;
if accept && (utils::is_zsh() || utils::is_fish() || utils::is_bash()) {
if accept
&& (utils::is_zsh() || utils::is_fish() || utils::is_bash() || utils::is_xonsh())
{
command = String::from("__atuin_accept__:") + &command;
}

Expand Down
21 changes: 21 additions & 0 deletions atuin/src/command/init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ pub enum Shell {
Fish,
/// Nu setup
Nu,
/// Xonsh setup
Xonsh,
}

impl Cmd {
Expand Down Expand Up @@ -140,12 +142,31 @@ bind -M insert \e\[A _atuin_bind_up";
}
}

fn init_xonsh(&self) {
let base = include_str!("../shell/atuin.xsh");
let (bind_ctrl_r, bind_up_arrow) = if std::env::var("ATUIN_NOBIND").is_ok() {
(false, false)
} else {
(!self.disable_ctrl_r, !self.disable_up_arrow)
};
println!(
"_ATUIN_BIND_CTRL_R={}",
if bind_ctrl_r { "True" } else { "False" }
);
println!(
"_ATUIN_BIND_UP_ARROW={}",
if bind_up_arrow { "True" } else { "False" }
);
println!("{base}");
}

pub fn run(self) {
match self.shell {
Shell::Zsh => self.init_zsh(),
Shell::Bash => self.init_bash(),
Shell::Fish => self.init_fish(),
Shell::Nu => self.init_nu(),
Shell::Xonsh => self.init_xonsh(),
}
}
}
67 changes: 67 additions & 0 deletions atuin/src/shell/atuin.xsh
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import subprocess
from prompt_toolkit.keys import Keys

$ATUIN_SESSION=$(atuin uuid).rstrip('\n')


@events.on_precommand
def _atuin_precommand(cmd: str):
cmd = cmd.rstrip("\n")
$ATUIN_HISTORY_ID = $(atuin history start -- @(cmd)).rstrip("\n")


@events.on_postcommand
def _atuin_postcommand(cmd: str, rtn: int, out, ts):
if "ATUIN_HISTORY_ID" not in ${...}:
return

duration = ts[1] - ts[0]
# Duration is float representing seconds, but atuin expects integer of nanoseconds
nanos = round(duration * 10 ** 9)
with ${...}.swap(ATUIN_LOG="error"):
# This causes the entire .xonshrc to be re-executed, which is incredibly slow
# This happens when using a subshell and using output redirection at the same time
# For more details, see https://github.com/xonsh/xonsh/issues/5224
# (atuin history end --exit @(rtn) -- $ATUIN_HISTORY_ID &) > /dev/null 2>&1
atuin history end --exit @(rtn) --duration @(nanos) -- $ATUIN_HISTORY_ID > /dev/null 2>&1
del $ATUIN_HISTORY_ID


def _search(event, extra_args: list[str]):
buffer = event.current_buffer
cmd = ["atuin", "search", "--interactive", *extra_args, "--", buffer.text]
# We need to explicitly pass in xonsh env, in case user has set XDG_HOME or something else that matters
env = ${...}.detype()
env["ATUIN_SHELL_XONSH"] = "t"

p = subprocess.run(cmd, stderr=subprocess.PIPE, encoding="utf-8", env=env)
result = p.stderr.rstrip("\n")
# redraw prompt - necessary if atuin is configured to run inline, rather than fullscreen
event.cli.renderer.erase()

if not result:
return

buffer.reset()
if result.startswith("__atuin_accept__:"):
buffer.insert_text(result[17:])
buffer.validate_and_handle()
else:
buffer.insert_text(result)


@events.on_ptk_create
def _custom_keybindings(bindings, **kw):
@bindings.add(Keys.ControlR, filter=_ATUIN_BIND_CTRL_R)
def r_search(event):
_search(event, extra_args=[])

@bindings.add(Keys.Up, filter=_ATUIN_BIND_UP_ARROW)
def up_search(event):
# Only trigger if the buffer is a single line
if not '\n' in buffer.text:
_search(event, extra_args=["--shell-up-key-binding"])
return

# Run the default behavior for up arrow
event.current_buffer.auto_up(count=event.arg)

0 comments on commit c56f8ff

Please sign in to comment.