├── .prettierrc.json ├── LICENSE ├── README.md ├── conf.d └── sponge.fish └── functions ├── _sponge_clear_state.fish ├── _sponge_on_exit.fish ├── _sponge_on_postexec.fish ├── _sponge_on_preexec.fish ├── _sponge_on_prompt.fish ├── _sponge_remove_from_history.fish ├── sponge_filter_failed.fish └── sponge_filter_matched.fish /.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "tabWidth": 2 3 | } 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Andrei Borisov 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 🧽 Sponge [![Releases](https://img.shields.io/github/release/meaningful-ooo/sponge.svg?label=&color=%23ffffff)](https://github.com/meaningful-ooo/sponge/releases/latest) 2 | 3 |
4 | 5 | [![Discord](https://img.shields.io/discord/776090526410604564?color=%235866f2&label=%20&logo=discord&logoColor=%23ffffff)](https://discord.gg/KEc2MMV3T9) [![Twitch Status](https://img.shields.io/twitch/status/borisovdev?color=%239146ff&label=%20&logo=twitch&logoColor=%23ffffff)](https://twitch.tv/borisovdev) 6 | 7 |
8 | 9 | > Don't you hate it when you spend half an hour searching for a command, finally find it and happily press `Enter` only to realize a couple of seconds later... it's not that one, it's another one you've entered two months ago, the one with the _typo_. 10 | 11 | > Ugh. Awful. Ungodly. Unproductive. Your day is ruined… unless you use _Sponge_. 12 | 13 | Sponge quietly runs in the background and keeps your shell history clean from typos, incorrectly used commands and everything you don't want to store due to privacy reasons. 14 | 15 | ## 💾 Installation 16 | 17 | Install with [Fisher](https://github.com/jorgebucaran/fisher): 18 | 19 | ```fish 20 | fisher install meaningful-ooo/sponge 21 | ``` 22 | 23 | ### 🤖 System requirements 24 | 25 | - [fish](http://fishshell.com) 3.2+ 26 | 27 | ## 🕹️ Usage 28 | 29 | Just use your shell as usual and enjoy typos-free history😎 30 | 31 | Sponge will automatically filter out all failed commands unless they have been in the history before. The last 2 entries are always available so you can quickly fix a misspelled command. 32 | 33 | > Sponge won’t filter commands retroactively. If you don’t want previously mistyped commands clogging up your search results, clear the history once after Sponge installation: 34 | 35 | ```fish 36 | history clear 37 | ``` 38 | 39 | ## ⚙️ Settings 40 | 41 | ### 💩 Filter failed 42 | 43 | By default Sponge will filter out all commands that don’t have `0` as an exit code. You can tweak which exit codes Sponge considers successful with `sponge_successful_exit_codes` variable: 44 | 45 | ```fish 46 | set sponge_successful_exit_codes 0 127 47 | ``` 48 | 49 | If you wish to filter out all failed commands regardless of whether they already have been in the history or not, change `sponge_allow_previously_successful` variable: 50 | 51 | ```fish 52 | set sponge_allow_previously_successful false 53 | ``` 54 | 55 | ### 🕵🏻 Filter by regex 56 | 57 | You can use the full power of regular expressions to filter out unwanted commands. Set `sponge_regex_patterns` variable and everything matched will be kept away from the history. For example, to filter out every command that contains IPv4 address, type: 58 | 59 | ```fish 60 | set sponge_regex_patterns '(?:\d{1,3}\.){3}\d{1,3}' 61 | ``` 62 | 63 | ### 🦥 Adjusting delay 64 | 65 | By default Sponge delays purging of filtered command so you can always access the last 2 history entries. If you want to remove commands immediately or increase the delay, change `sponge_delay` variable: 66 | 67 | ```fish 68 | set sponge_delay 5 69 | ``` 70 | 71 | ### ⛔ Purge only on exit 72 | 73 | Sometimes you want to ignore `sponge_delay` variable and access the whole history of the current session. In such cases you can instruct Sponge to purge entries only on shell exit with `sponge_purge_only_on_exit` variable: 74 | 75 | ```fish 76 | set sponge_purge_only_on_exit true 77 | ``` 78 | 79 | > 💡 Did you know you can change settings only for the current session? Just add `--global` flag when setting any variable and it won't be preserved after shell exit. 80 | 81 | ### 🤓 Custom filters 82 | 83 | Sponge works by invoking an array of _filters_. You can plug into this mechanism by defining your own filters. 84 | 85 | Filter is simply a function with a specific call signature: 86 | 87 | | **Argument** | **Name** | **Description** | 88 | | ------------ | ----------------------- | ------------------------------------------------------------------------------- | 89 | | 1 | `command` | The exact command that was entered | 90 | | 2 | `exit_code` | The exit code of the command | 91 | | 3 | `previously_in_history` | `true` or `false` flag indicating if the command has been in the history before | 92 | 93 | Return with exit status `0` to filter out provided command and anything else to keep the command in the history. 94 | 95 | You can define your filter in `config.fish` or as a standalone function in fish `functions` folder. 96 | 97 | > Be mindful of what you put in filters, as they are run synchronously after each command execution and can slow down your prompt in case of compute-intensive tasks or network requests. 98 | 99 | After that you need to register your filter with Sponge by adding its name in `sponge_filters` variable: 100 | 101 | ```fish 102 | set --append sponge_filters my_awesome_filter 103 | ``` 104 | 105 | Make sure to append `sponge_filters` like in the example above unless you want to disable the built in filters: 106 | 107 | - [`sponge_filter_failed`](https://github.com/meaningful-ooo/sponge/blob/main/functions/sponge_filter_failed.fish) filters by command exit code 108 | - [`sponge_filter_matched`](https://github.com/meaningful-ooo/sponge/blob/main/functions/sponge_filter_matched.fish) filters using regex patterns 109 | 110 | ## ©️ License 111 | 112 | [MIT](LICENSE) 113 | 114 | # 🏴‍☠️ 🏰 💎 Meaningful 115 | 116 | We are the first ever blockchain state. [More](https://meaningful.ooo). 117 | -------------------------------------------------------------------------------- /conf.d/sponge.fish: -------------------------------------------------------------------------------- 1 | # Sponge version 2 | set --global sponge_version 1.1.0 3 | 4 | # Allow to repeat previous command by default 5 | if not set --query --universal sponge_delay 6 | set --universal sponge_delay 2 7 | end 8 | 9 | # Purge entries both after `sponge_delay` entries and on exit by default 10 | if not set --query --universal sponge_purge_only_on_exit 11 | set --universal sponge_purge_only_on_exit false 12 | end 13 | 14 | # Add default filters 15 | if not set --query --universal sponge_filters 16 | set --universal sponge_filters sponge_filter_failed sponge_filter_matched 17 | end 18 | 19 | # Don't filter out commands that already have been in the history by default 20 | if not set --query --universal sponge_allow_previously_successful 21 | set --universal sponge_allow_previously_successful true 22 | end 23 | 24 | # Consider `0` the only successful exit code by default 25 | if not set --query --universal sponge_successful_exit_codes 26 | set --universal sponge_successful_exit_codes 0 27 | end 28 | 29 | # No active regex patterns by default 30 | if not set --query --universal sponge_regex_patterns 31 | set --universal sponge_regex_patterns 32 | end 33 | 34 | # Attach event handlers 35 | functions --query \ 36 | _sponge_on_prompt \ 37 | _sponge_on_preexec \ 38 | _sponge_on_postexec \ 39 | _sponge_on_exit 40 | 41 | # Initialize empty state for the first run 42 | function _sponge_install --on-event sponge_install 43 | set --global _sponge_current_command '' 44 | set --global _sponge_current_command_exit_code 0 45 | set --global _sponge_current_command_previously_in_history false 46 | end 47 | 48 | # Clean up variables 49 | function _sponge_uninstall --on-event sponge_uninstall 50 | _sponge_clear_state 51 | set --erase sponge_version 52 | end 53 | -------------------------------------------------------------------------------- /functions/_sponge_clear_state.fish: -------------------------------------------------------------------------------- 1 | function _sponge_clear_state 2 | set --erase --global _sponge_current_command 3 | set --erase --global _sponge_current_command_exit_code 4 | set --erase --global _sponge_current_command_previously_in_history 5 | end 6 | -------------------------------------------------------------------------------- /functions/_sponge_on_exit.fish: -------------------------------------------------------------------------------- 1 | function _sponge_on_exit --on-event fish_exit 2 | sponge_delay=0 _sponge_remove_from_history 3 | end 4 | -------------------------------------------------------------------------------- /functions/_sponge_on_postexec.fish: -------------------------------------------------------------------------------- 1 | function _sponge_on_postexec --on-event fish_postexec 2 | set --global _sponge_current_command_exit_code $status 3 | 4 | # Remove command from the queue if it's been added previously 5 | if set --local index (contains --index -- $_sponge_current_command $_sponge_queue) 6 | set --erase _sponge_queue[$index] 7 | end 8 | 9 | # Ignore empty commands 10 | if test -n $_sponge_current_command 11 | set --local command '' 12 | # Run filters 13 | for filter in $sponge_filters 14 | if $filter \ 15 | $_sponge_current_command \ 16 | $_sponge_current_command_exit_code \ 17 | $_sponge_current_command_previously_in_history 18 | set command $_sponge_current_command 19 | break 20 | end 21 | end 22 | set --prepend --global _sponge_queue $command 23 | end 24 | end 25 | -------------------------------------------------------------------------------- /functions/_sponge_on_preexec.fish: -------------------------------------------------------------------------------- 1 | function _sponge_on_preexec --on-event fish_preexec \ 2 | --argument-names command 3 | _sponge_clear_state 4 | 5 | set --global _sponge_current_command $command 6 | 7 | builtin history search --case-sensitive --exact --max=1 --null $command \ 8 | | read --local --null found_entries 9 | 10 | # If a command is in the history and in the queue, ignore it, like if it wasn’t in the history 11 | if test (count $found_entries) -ne 0; and not contains $command $_sponge_queue 12 | set --global _sponge_current_command_previously_in_history true 13 | else 14 | set --global _sponge_current_command_previously_in_history false 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /functions/_sponge_on_prompt.fish: -------------------------------------------------------------------------------- 1 | function _sponge_on_prompt --on-event fish_prompt 2 | if test $sponge_purge_only_on_exit = false 3 | _sponge_remove_from_history 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /functions/_sponge_remove_from_history.fish: -------------------------------------------------------------------------------- 1 | function _sponge_remove_from_history 2 | 3 | while test (count $_sponge_queue) -gt $sponge_delay 4 | builtin history delete --case-sensitive --exact -- $_sponge_queue[-1] 5 | set --erase _sponge_queue[-1] 6 | end 7 | 8 | builtin history save 9 | end 10 | -------------------------------------------------------------------------------- /functions/sponge_filter_failed.fish: -------------------------------------------------------------------------------- 1 | function sponge_filter_failed \ 2 | --argument-names command exit_code previously_in_history 3 | 4 | if test $previously_in_history = true -a $sponge_allow_previously_successful = true 5 | return 1 6 | end 7 | 8 | if contains $exit_code $sponge_successful_exit_codes 9 | return 1 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /functions/sponge_filter_matched.fish: -------------------------------------------------------------------------------- 1 | function sponge_filter_matched \ 2 | --argument-names command 3 | 4 | for pattern in $sponge_regex_patterns 5 | if string match --regex --quiet $pattern -- $command 6 | return 7 | end 8 | end 9 | 10 | return 1 11 | end 12 | --------------------------------------------------------------------------------