Compare commits

..

14 commits
v1.0.0 ... main

Author SHA1 Message Date
aa00038f28 (chore): better repaint handling 2025-08-28 16:27:22 -05:00
62cd9b2f17 (chore): update documentation fdor new implemented features 2025-07-26 22:25:40 -05:00
768bce39ec (feat): add based maintenance to perform analyze + vacuum
It will help if your database has been runing for a very long time
2025-07-26 22:25:27 -05:00
88cbb3cc9b (chore): add more database improvements 2025-07-26 22:24:16 -05:00
2afe4b3aba (feat): add BASED_EXCLUDED_PATHS to exclude directories from history
There are cases where you want to exclude some paths from being indexed. E.g: `..`, `/tmp/*`, and others.
2025-07-26 22:23:57 -05:00
0206728145 Revert "(chore): change function name"
This reverts commit b85004121f.
2025-06-19 17:23:35 -05:00
b85004121f (chore): change function name 2025-06-19 14:30:12 -05:00
Daniel Bretoi
97525dd0e2
use relative source path (#1)
$__fish_config_dir    could be set to something completely different. but using a relative path here is safe either way. This way it can be sourced anywhere, even if the repo is just cloned in some random place.
2025-06-18 20:00:46 -05:00
e7f2351f06 (feat): better keybinding for fzf
# TAB: Accept the current selection but do not execute it, never
# ENTER: Accept the current selection and execute it if confirmation is set
2025-06-05 00:44:57 -05:00
1eeb710cb7 (feat): add completions 2025-06-05 00:27:07 -05:00
6ed4d3a32d (chore): optimize fzf popup 2025-06-05 00:18:38 -05:00
d7c44fae63 (feat): show the last command on top per-directory 2025-06-05 00:06:29 -05:00
f1695694ed (chore): update README 2025-06-04 23:55:47 -05:00
998ad80afd (chore): update README 2025-06-04 20:16:11 -05:00
10 changed files with 109 additions and 28 deletions

View file

@ -1,15 +1,16 @@
# A context-based autocompletion plugin for the Fish shell # A context-based autocompletion plugin for the Fish shell
based.fish is a lightweight Fish plugin that provides context-based autocompletion for commands, options, and arguments. It enhances the default Fish shell completion system by offering more intelligent and context-aware suggestions. For example, it suggests commands based on the frequency of use, date of use, and the context of the current command line such as the path where you are, the command you are typing, etc. based.fish is a lightweight Fish plugin that provides context-based autocompletion for commands, options, and arguments. It enhances the default Fish shell completion system by offering more intelligent and context-aware suggestions. For example, it suggests commands based on the frequency of use, date of use, and the context of the current command line such as the path where you are, the command you are typing, etc. See the [other tools](#other-tools) section for a comparison with similar tools.
## Features ## Features
- Context-aware autocompletion for commands, options, and arguments. - Context-aware autocompletion for commands, options, and arguments.
- Supports combining different history sources, such as the current working directory, the global suggestions, and the previous command.
- Directory-aware completions that take into account the current working directory.
- Integration with fzf for a better selection experience. - Integration with fzf for a better selection experience.
- Easy installation and setup with Fisher. - Easy installation and setup with Fisher.
- Support for importing existing Fish history. - Support for importing existing Fish history.
- Customizable configuration options to tailor the behavior of the plugin. - Customizable configuration options to tailor the behavior of the plugin.
- Directory-aware completions that take into account the current working directory.
- Statistics about command usage, such as most frequently used commands, options, and arguments. - Statistics about command usage, such as most frequently used commands, options, and arguments.
- Customizable keybindings for navigating and selecting completions. - Customizable keybindings for navigating and selecting completions.
- Support for disabling fuzzy matching and confirmation prompts. - Support for disabling fuzzy matching and confirmation prompts.
@ -28,7 +29,7 @@ based.fish uses a SQLite database to store command history and statistics. It an
- It considers the date of the last use, the frequency of use, and the context of the current command line input. Suggestions are made based on this information. - It considers the date of the last use, the frequency of use, and the context of the current command line input. Suggestions are made based on this information.
- If you are in a directory where you have previously used a command multiple times, it will suggest that command first, then the second most used command, and so on. - If you are in a directory where you have previously used a command multiple times, it will suggest that command first, then the second most used command, and so on.
- For convenience, during the current session, it will always suggest your previous command first and then go back to the most used commands in the current directory. - For convenience, during the current session, it will always suggest your previous command first and then append the most used commands in the current directory, and then then global ones. It's to replicate the "normal" behavior of most shells.
## Installation ## Installation
@ -67,12 +68,20 @@ $ based stats
``` ```
This will display statistics about your command usage, such as the most frequently used commands, options, and arguments. This will display statistics about your command usage, such as the most frequently used commands, options, and arguments.
For database maintenance (recommended to run if you notice performance issues):
```fish
$ based maintenance
```
This will optimize the database by running VACUUM and ANALYZE operations to keep it performing well.
## Configuration ## Configuration
You can customize the behavior of based.fish by setting environment variables in your Fish shell: You can customize the behavior of based.fish by setting environment variables in your Fish shell:
- `BASED_NO_CONFIRMATION`: If set to `1`, automatically executes the selected suggestion without confirmation, otherwise, it requires another Enter key press to execute the suggestion. - `BASED_NO_CONFIRMATION`: If set to `1`, automatically executes the selected suggestion without confirmation, otherwise, it requires another Enter key press to execute the suggestion.
- `BASED_NO_FUZZY`: If set to `1`, disables fuzzy matching for completions and only commands that start with the typed prefix will be suggested. - `BASED_NO_FUZZY`: If set to `1`, disables fuzzy matching for completions and only commands that start with the typed prefix will be suggested.
- `BASED_EXCLUDED_PATHS`: A list of path patterns to exclude from history logging. Supports glob patterns like `*` and `?`. Useful for excluding temporary directories, sensitive locations, or paths where you don't want command history tracked.
E.g. to disable fuzzy behavior when searching for completions E.g. to disable fuzzy behavior when searching for completions
@ -80,6 +89,12 @@ E.g. to disable fuzzy behavior when searching for completions
$ set -Ux BASED_NO_FUZZY 1 $ set -Ux BASED_NO_FUZZY 1
``` ```
E.g. to exclude specific paths from history tracking
```fish
$ set -Ux BASED_EXCLUDED_PATHS "/tmp/*" "/var/tmp/*" "$HOME/Downloads"
```
The keybindings for the completions are as follows: The keybindings for the completions are as follows:
- `Arrow Up` and `Arrow Down`: Navigate through the suggestions of the smart history. - `Arrow Up` and `Arrow Down`: Navigate through the suggestions of the smart history.
@ -92,6 +107,10 @@ Keybinds can be customized by modifying the `$HOME/.config/fish/functions/based_
![based.fish demonstration](assets/based_fish_plugin.gif) ![based.fish demonstration](assets/based_fish_plugin.gif)
### Other tools
- [Atuin](https://github.com/atuinsh/atuin): a very well-known. It's a great tool, but doesn't provide what I wanted, it basically shows you the most recent commands, it does provide per-directory completions, but it's very limited. Commands are always shown in the recent order, not per-directory repeats (unless you type something or set the "directory" filter, but then that limits the history to that directory only), and even with the filters, these filters works separately and you have to switch between them for history, they can't be combined and it's unlikely to happen https://github.com/atuinsh/atuin/issues/1611#issuecomment-1908451910, this is a dealbreaker **for me**. I discovered it trying to switch to Atuin.
## Contributing ## Contributing
If you want to contribute to based.fish, feel free to open issues or pull requests on the GitHub repository. Contributions are welcome! If you want to contribute to based.fish, feel free to open issues or pull requests on the GitHub repository. Contributions are welcome!

7
completions/based.fish Normal file
View file

@ -0,0 +1,7 @@
# Fish shell completion script for the Based Fish plugin
complete -c based -n __fish_use_subcommand -f -a init -d "Initialize the Based database"
complete -c based -n __fish_use_subcommand -f -a import -d "Import Fish history into Based"
complete -c based -n __fish_use_subcommand -f -a stats -d "Show Based statistics"
complete -c based -n __fish_use_subcommand -f -a reset -d "Reset Based state"
complete -c based -n __fish_use_subcommand -f -a maintenance -d "Perform database maintenance"
complete -c based -n __fish_use_subcommand -f -a help -d "Show help message"

View file

@ -1,4 +1,4 @@
# Load the based logger (for fish_postexec event) # Load the based logger (for fish_postexec event)
source ~/.config/fish/functions/__based_log.fish source (status dirname)/../functions/__based_log.fish
# Load keybindings (↑ for smart history, Ctrl+g for fzf popup) # Load keybindings (↑ for smart history, Ctrl+g for fzf popup)
source ~/.config/fish/functions/based_user_key_bindings.fish source (status dirname)/../functions/based_user_key_bindings.fish

View file

@ -44,10 +44,12 @@ function __based
else else
set -f results (sqlite3 -batch $db " set -f results (sqlite3 -batch $db "
SELECT DISTINCT cmd FROM ( SELECT DISTINCT cmd FROM (
-- Get the most recent command across all paths -- Get the most recent command across the current path to emulate the normal history behavior
-- This ensures that the most recent command is always at the top
SELECT cmd, max_ts, counter, priority FROM ( SELECT cmd, max_ts, counter, priority FROM (
SELECT cmd, MAX(ts) as max_ts, MAX(counter) as counter, 0 as priority SELECT cmd, MAX(ts) as max_ts, MAX(counter) as counter, 0 as priority
FROM log FROM log
WHERE path = '$path'
GROUP BY cmd GROUP BY cmd
ORDER BY max_ts DESC ORDER BY max_ts DESC
LIMIT 1 LIMIT 1

View file

@ -1,21 +1,29 @@
function __based_fzf_popup function __based_fzf_popup
set -l suggestions (__based) # TAB: Accept the current selection but do not execute it, never
if test (count $suggestions) -gt 0 # ENTER: Accept the current selection and execute it if confirmation is set
set -l chosen (printf "%s\n" $suggestions | fzf --height 40% --reverse --prompt='Context > ' --query="$prefix" --no-sort --exact --border) set -l out (__based | fzf \
--height 50% --reverse --prompt='Command > ' \
--no-sort --exact --border \
--bind "tab:accept" \
--expect tab,enter)
if test -n "$chosen" set -l key (echo $out[1])
set -l cleaned (string trim -- $chosen) set -l chosen (string join "\n" $out[2..-1] | string collect)
if test -n "$cleaned"
commandline -r -- "$cleaned" if test -n "$chosen"
commandline -f repaint commandline -r -- "$chosen"
# If BASED_NO_CONFIRMATION is set to a non-zero value, execute the command immediately # Prevent autocomplete samples from remaining before the selected command.
if set -q BASED_NO_CONFIRMATION; and test "$BASED_NO_CONFIRMATION" != 0 # i.e: if you run `cd`, then arrow up, and select a command, the initial `cd` will be
commandline -f execute # visible before the selected command, like: `cd cd <path>`. It doesn't affect functionality,
end # but it can be visually confusing.
end commandline -f repaint
else
commandline -f repaint # Only execute if the user pressed ENTER and confirmation is set
return if test "$key" = enter; and set -q BASED_NO_CONFIRMATION; and test "$BASED_NO_CONFIRMATION" != 0
commandline -f execute
end end
end end
# Update the display for commands like directory changes
commandline -f repaint
end end

View file

@ -18,6 +18,8 @@ function __based_init_db
CREATE INDEX IF NOT EXISTS idx_log_cmd ON log(cmd); CREATE INDEX IF NOT EXISTS idx_log_cmd ON log(cmd);
CREATE INDEX IF NOT EXISTS idx_log_path_ts ON log(path, ts); CREATE INDEX IF NOT EXISTS idx_log_path_ts ON log(path, ts);
CREATE INDEX IF NOT EXISTS idx_log_path_cmd ON log(path, cmd); CREATE INDEX IF NOT EXISTS idx_log_path_cmd ON log(path, cmd);
CREATE INDEX IF NOT EXISTS idx_log_counter_ts ON log(counter DESC, ts DESC);
CREATE INDEX IF NOT EXISTS idx_log_cmd_like ON log(cmd COLLATE NOCASE);
" "
echo "Based initialized. You can also import your fish history with 'based import'." echo "Based initialized. You can also import your fish history with 'based import'."

View file

@ -13,6 +13,15 @@ function __based_log --on-event fish_preexec
return return
end end
# Check if path should be excluded
if set -q BASED_EXCLUDED_PATHS
for excluded_pattern in $BASED_EXCLUDED_PATHS
if string match -q $excluded_pattern $path
return
end
end
end
set cmd (string replace -a "'" "''" -- $cmd) set cmd (string replace -a "'" "''" -- $cmd)
set path (string replace -a "'" "''" -- $path) set path (string replace -a "'" "''" -- $path)

View file

@ -0,0 +1,25 @@
function __based_maintenance
set -l db ~/.local/share/fish/based/based.db
if not test -f $db
echo "Database not found. Run 'based init' first."
return 1
end
echo "Performing database maintenance..."
# Get database size before
set -l size_before (du -h $db | cut -f1)
# Vacuum the database
sqlite3 $db "VACUUM;"
# Update statistics
sqlite3 $db "ANALYZE;"
# Get database size after
set -l size_after (du -h $db | cut -f1)
echo "Database maintenance completed."
echo "Size before: $size_before"
echo "Size after: $size_after"
end

View file

@ -3,5 +3,6 @@ function __based_reset_state
# Unset all variables related to Based state # Unset all variables related to Based state
set -e BASED_NO_CONFIRMATION set -e BASED_NO_CONFIRMATION
set -e BASED_NO_FUZZY set -e BASED_NO_FUZZY
set -e BASED_EXCLUDED_PATHS
echo "Based state has been reset." echo "Based state has been reset."
end end

View file

@ -8,14 +8,22 @@ function based
__based_stats __based_stats
case reset case reset
__based_reset_state __based_reset_state
case maintenance vacuum
__based_maintenance
case help '*' case help '*'
echo "Usage: based init|import|stats|reset|help" echo "Usage: based init|import|stats|reset|maintenance|help"
echo "Commands:" echo "Commands:"
echo " init - Initialize the Based database" echo " init - Initialize the Based database"
echo " import - Import fish history into Based" echo " import - Import fish history into Based"
echo " stats - Show Based statistics" echo " stats - Show Based statistics"
echo " reset - Reset Based state (clears variables)" echo " reset - Reset Based state (clears variables)"
echo " help - Show this help message" echo " maintenance - Perform database maintenance (vacuum & analyze)"
echo " help - Show this help message"
echo ""
echo "Configuration variables:"
echo " BASED_NO_CONFIRMATION - Skip confirmation prompts"
echo " BASED_NO_FUZZY - Disable fuzzy matching"
echo " BASED_EXCLUDED_PATHS - Paths to exclude from history (glob patterns)"
case '*' case '*'
echo "Unknown command: $argv[1]" echo "Unknown command: $argv[1]"
echo "Use 'based help' for usage information." echo "Use 'based help' for usage information."