├── .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 [](https://github.com/meaningful-ooo/sponge/releases/latest)
2 |
3 |
4 |
5 | [](https://discord.gg/KEc2MMV3T9) [](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 |
--------------------------------------------------------------------------------