* Print literal control characters to non terminals
Previous 'fix' to prevent control sequences being interpreted when they
shouldn't have been also prevented them being used when they should have
been. This checks if the output is to a terminal (where control
sequences shouldn't be interpreted) before escaping control characters.
* Update atuin/src/command/client/search.rs
Co-authored-by: Ellie Huxtable <ellie@elliehuxtable.com>
---------
Co-authored-by: Ellie Huxtable <ellie@elliehuxtable.com>
If a previous command in the history contained a literal control
character (eg via Ctrl-v, Ctrl-[), when the command was printed, the
control character was printed and whatever control sequence it was part
of was interpreted by the terminal. For instance, if a command contained
the SGR sequence `^[[31m`, all subsequent output from `atuin history
list` would be in red.
Slightly less of a problem, control characters would also not appear in
the interactive search widget although they would be printed when
selected. This meant `echo '^[[31foo'` would appear as `echo '[31foo'`.
When the entry was selected, the same problem as before would occur and,
for the example above, `echo 'foo'` would be printed with 'foo' in red.
When copied, this command would not behave the same as the original as
it would be missing the control sequence.
This adds an extension trait to add a method to anything that behaves
like a string to escape ascii control characters and return a string
that can be printed safely. This string can then be copied and run
directly without having to add the control characters back.
* feat: add history rebuild
This adds a function that will
1. List all history from the store
2. Segment by create/delete
3. Insert all creates into the database
4. Delete all deleted
This replaces the old history sync.
Presently it's incomplete. There is no incremental rebuild, it can only
do the entire thing at once.
This is ran by `atuin store rebuild history`
* fix tests
* add incremental sync
* add auto sync
Imagine the scenario where a sync fails. The function touched here will
never save the sync time.
That means that external to this function, the sync never happened. The
next command will try and start one immediately.
The happy scenario is that this succeeds. The unhappy scenario is that
this fails. Fails, and isn't saved, so we try again...
Should add proper backoff but this is a good start.
* Fix fish integration on older fishes
- On fish 3.3 the bash-style `$(...)` doesn't work, we should use `(...)`
- Also quoting `"(moo)"` on older fishes gives a literal `moo`
- The result of a `(subcommand)` is a single token, so no need to quote it, anyway
Tested by making the change, executing `cargo run -- init fish --disable-up-arrow` and then
executing that shell script on a system with fish 3.3, as well as 3.6 and observing both still work.
Fixes#1562.
* Alternative way of fixing the problem. Compatible with 3.3 and 3.4+
1. Some shells/terminals seem to directly bind ctrl-i to be tab :( Use
ctrl-o for the inspector instead
2. Shorten the help text so it doesn't get squished
* feat(config): add vim option to config
* feat(ui): simple vim mode
* fix(windows): windows sadly doesn't support the stuff
* feat(ui): blinking
* fix(merge)
* revert: reverts some debugging stuff
* feat(ui): changes the defaut to insert, don't know what should be the default
* feat(ui): implements some vim parity
* doc: adds this to the docs
* docs(keybindings): adds vim mode keybindsings to the list of keybindings
* refactor: rustfmt and remove the docs for pr in own repo
* refactor: use execute!
* Update atuin/src/command/client/search/interactive.rs
---------
Co-authored-by: Ellie Huxtable <ellie@elliehuxtable.com>
* Begin work on command inspector
This is a separate pane in the interactive mode that allows for
exploration and inspecting of specific commands.
I've restructured things a bit. It made logical sense that things
were nested under commands, however the whole point of `atuin` is to
provide commands. Breaking things out like this enables a bit less
crazy nesting as we add more functionality to things like interactive
search. I'd like to add a few more interactive things and it was
starting to feel very cluttered
* Some vague tab things
* functioning inspector with stats
* add interactive delete to inspector
* things
* clippy
* borders
* sus
* revert restructure for another pr
* Revert "sus"
This reverts commit d4bae8cf61.
* fix(bash): add a guard for interactive shells
* fix(bash): add a guard for the Bash version
* fix(bash): localize READLINE_LINE in bash < 4
In bash < 4, the variables READLINE_LINE and READLINE_POINT are not
supported for the shell commands called by `bind -x`. Even if it is
not supported, atuin works in not a bad way. However, this sometimes
causes a strange behavior by the remaining values of READLINE_LINE set
in the previous calls of __atuin_history. In bash < 4, we can
consistently use an empty string instead of $READLINE_LINE, and the
changes to READLINE_LINE and READLINE_POINT should be localized within
the function.
* fix(bash): add guard for double initialization
In bash, it is customary to reload the settings by sourcing `.bashrc`
again after modifying it. In such a case, `eval "$(atuin init bash)"`
is executed again. This registers duplicate hooks to
`preexec_functions` and `precmd_functions`. To prevent this in this
patch, we introduce an include guard, so that the initialization is
not performed more than once.
Given some of the questions we've had lately, I think it's sensible to
add extended help to the top of the Atuin window.
Future plans: Ctrl-<something else> to open up a help popup, with all
common keys
* feat(bash): support high-resolution timing without blesh
For the integration using bash-preexec, this measures the execution
time of the command using EPOCHREALTIME without the support by ble.sh.
This is not as accurate as the measurement by ble.sh as it contains
also the processing time of the preexec and precmd hooks, but it is
still free from the fork cost.
* fix(shell): work around custom IFS for duration
When a custom IFS is set by the user, the word splitting of
${duration:+--duration "$duration"} does not work as expected. We
instead use the form "--duration=$duration" with the word splitting
being disabled.
* style(bash): make indentation consistent
Initially, in this file, the first level is indented by four spaces,
and additional levels are indented by adding two spaces. However,
this does not seem intentional because the other files, such as
atuin.zsh, are consistently indented by four spaces for any levels.
The indentation was gradually fixed to use four spaces when the
relevant code is updated, but there are still remaining parts using
two spaces. In this patch, the remaining parts are updated to use the
consistent indentation of four spaces.
* style(bash): remove extra quotations on rhs of assignments
On the right-hand sides of assignments, the quoting of the variable
expansions are not needed because they are not subject to the word
splitting and the pathname expansions.
* style(bash): strip `{` and `}` from `${var}` when not needeed
* style(bash): do not use unnecessary quoting in the conditional commands
In the conditional commands [[ ... ]], the words are not subject to
the word splitting and the pathname expansions, so we do not need to
quote the expansions except for the right-hand sides of ==, !=, and
=~, where the quoting has a special meaning. In the first place, the
syntax [[ .. ]] is introduced to resolve the issue of the quoting, so
it is natural to use the unquoted form inside [[ ... ]] by default.
In this patch, we use the unquoted form of expansions.
* style(bash): prefer [[ $a && ! $b ]] to [[ -n $a && -z $b ]]
* style(bash): put "then" in the same line as "if"
This is also the format that Bash outputs with `bash --pretty-print
FILE` or `declare -f FUNC`.
When a child shell session is started from another shell session
(parent session), the environment variable ATUIN_HISTORY_ID set by the
parent session causes Atuin's precmd hook of the child session to be
unexpectedly performed before the first call of Atuin's preexec hook.
In this patch, we clear ATUIN_HISTORY_ID (possibly set by the parent
session) on the startup of the session.
The columns referred to in this PR, were for some reason created with
defaults. When created years ago, they were `bigserial` not `bigint`.
The defaults were never actually used, as verified by
1. Checking the value of the sequences on the database
2. Checking the code
So we're safe to clean them up.
* fix(bash): improve up key in multiline mode of ble.sh
ble.sh has a multiline mode where pressing [up] can be used to move to
the previous line. The command history is loaded only when the [up]
key is pressed when the cursor is in the first line. However, with
Atuin's integration, the [up] key always causes Atuin's history search
and cannot be used to move to the previous line when the cursor is not
in the first line. There is also another situation that the [up] key
does not load the command history.
In this patch, with ble.sh, we perform Atuin's history search only in
the situation where the command history is loaded in the original
binding of ble.sh.
* fix(init): perform bind on explicitly specified keymaps
With the current implementation, the keybindings to [C-r] and [up] are
only set up in the currently activated keymaps in Bash. As a result,
if the user changes the keymap after `eval "$(atuin init bash)"`,
Atuin's keybindings do not take effect. In this patch, we bind
Atuin's keybindings in all the keymaps (emacs, vi-insert, and
vi-command) by explicitly specifying them (as done for the Zsh
integration). The keybinding to "k" in the vi-command keymap is also
added to make it consistent with the Zsh integration.
* fix(init): work around limitation of "bind -x" in bash <= 4.2
In bash <= 4.2, "bind -x" with a key sequence with more than two bytes
does not work properly. Inputting the key sequence will produce an
error message saying "bash: bash_execute_unix_command: cannot find
keymap for command", and the shell command is not executed.
To work around this, we can first translate the key sequences to
another key sequence with two bytes and run the shell command through
the two-byte key sequence. In this patch, we use \C-x\C-p as the
two-byte key sequence.
* refactor(bash): move the inlined binding scripts to atuin.bash
* refactor(init): use `is_ok()` instead of negating `is_err()`
Co-authored-by: Ellie Huxtable <ellie@elliehuxtable.com>
---------
Co-authored-by: Ellie Huxtable <ellie@elliehuxtable.com>
When the user sets a custom value of IFS, the up keybinding may fail
because the option `--shell-up-key-binding` passed to
`__atuin_history` is broken by the word splitting of the shell. For
example, when the user sets IFS=-, `atuin` called from __atuin_history
receives `shell up key binding <content>` as the search string.
$ IFS=-
$ echo [up] # <-- this does not work as expected
Note that the problem only happens with the plain Bash without ble.sh.
The problem does not arise within ble.sh because ble.sh separates the
user environment and the line-editor environment by saving/restoring
the shell settings. The keybindings are processed in the line-editor
environment, so the custom IFS set by the user does not affect it.
In this patch, we properly quote the arguments to the atuin command.
This fixes the second issue of "0s or wrong command duration" reported
at https://github.com/atuinsh/atuin/issues/1003.
The problem is that, with bash-preexec, the preexec hook may be called
even for the commands executed by the keybindings.
* In particular, the preexec is called before the command
`__atuin_history` is executed on pressing [C-r] and [up]. In this
case, $1 passed to `__atuin_preexec` contains the last entry in the
command history, so `atuin history start` is called for the last
command. As a result, pressing [C-r] and [up] clears the duration
of the last command. This causes the reported 0s duration.
* Furthermore, the precmd hook corresponding to the keybinding command
will not be called, so the duration is only filled when the next
user command starts. This replaces the duration of the last command
with the time interval between the last press of [C-r] or [up] and
the start time of the next command. This causes the reported wrong
duration.
There is no general and robust way to distinguish the preexec
invocation for keybindings from that for the user commands, but in
this patch we exclude the preexec invocation for Atuin's keybindings
[C-r] and [up] at least.
* feat: rework record sync for improved reliability
So, to tell a story
1. We introduced the record sync, intended to be the new algorithm to
sync history.
2. On top of this, I added the KV store. This was intended as a simple
test of the record sync, and to see if people wanted that sort of
functionality
3. History remained syncing via the old means, as while it had issues it
worked more-or-less OK. And we are aware of its flaws
4. If KV syncing worked ok, history would be moved across
KV syncing ran ok for 6mo or so, so I started to move across history.
For several weeks, I ran a local fork of Atuin + the server that synced
via records instead.
The record store maintained ordering via a linked list, which was a
mistake. It performed well in testing, but was really difficult to debug
and reason about. So when a few small sync issues occured, they took an
extremely long time to debug.
This PR is huge, which I regret. It involves replacing the "parent"
relationship that records once had (pointing to the previous record)
with a simple index (generally referred to as idx). This also means we
had to change the recordindex, which referenced "tails". Tails were the
last item in the chain.
Now that we use an "array" vs linked list, that logic was also replaced.
And is much simpler :D
Same for the queries that act on this data.
----
This isn't final - we still need to add
1. Proper server/client error handling, which has been lacking for a
while
2. The actual history implementation on top
This exists in a branch, just without deletions. Won't be much to
add that, I just don't want to make this any larger than it already
is
The _only_ caveat here is that we basically lose data synced via the old
record store. This is the KV data from before.
It hasn't been deleted or anything, just no longer hooked up. So it's
totally possible to write a migration script. I just need to do that.
* update .gitignore
* use correct endpoint
* fix for stores with length of 1
* use create/delete enum for history store
* lint, remove unneeded host_id
* remove prints
* add command to import old history
* add enable/disable switch for record sync
* add record sync to auto sync
* satisfy the almighty clippy
* remove file that I did not mean to commit
* feedback
This enabled the Kitty Keyboard Protocol
Read more here: https://sw.kovidgoyal.net/kitty/keyboard-protocol/
No change on unsupported terminals, but means in the future we can be
more creative with keybinding depending on terminal.
Tested on Alacritty and events come through with all modifiers
supported.
Will be useful for #193