Closed horeah closed 1 year ago
Here comes an additional approach resp. idea for removing command history entries, which originates from another idea I had for PyCmd some day:
I additionally have a "history.bat" file in my PATH for some years now, which simply does this:
@type %APPDATA%\PyCmd\history
That way you can search N commands in command history like you're used to do on Linux, e.g.:
history | findstr "something"
Which gives you a nice search result overview sometimes and makes searching easier. I also love the UP+DOWN key search feature of PyCmd and intensively use it. But they are both slightly different use cases.
So maybe just implement a 'history' command directly in PyCmd (which can optionally be activated in init.py). So there's no need for a history.bat file.
Now if this optional internal 'history' command would behave like on Linux it would: a) Prepend line numbers before each command b) Know options like "-d" to remove specific entries from history, e.g. "history -d 123"
PS: Thus maybe also implement the Linux shell feature "!" (plus history line number) and activate it if 'history' is activated in init.py.
history
1 cd abc
3 cd ..
!1
1. I additionally have a "history.bat" file in my PATH for some years now, which simply does this:
@type %APPDATA%\PyCmd\history
That way you can search N commands in command history like you're used to do on Linux, e.g.:
history | findstr "something"
This is a cool idea!
2. So maybe just implement a 'history' command directly in PyCmd (which can optionally be activated in init.py). So there's no need for a history.bat file.
As long as the functionality can be easily implemented as an external command (e.g. batch file), I am not inclined to move it inside PyCmd.
Now if this optional internal 'history' command would behave like on Linux it would: a) Prepend line numbers before each command This can also be achieved with an external script (e.g. "cat -n")
b) Know options like "-d" to remove specific entries from history, e.g. "history -d 123"
This is a reasonable interface, but I am hoping we can work out (possibly: in addition) something more user-friendly/interactive interface.
PS: Thus maybe also implement the Linux shell feature "!" (plus history line number) and activate it if 'history' is activated in init.py.
history 1 cd abc 3 cd .. !1
I am not sure that this is feasible in the general case; PyCmd actually uses
cmd.exe
to execute all but the simplest commands; and parsing the cmd syntax to ensure that we correctly replace the ! in complex command is virtually impossible (this is not an exaggeration; the syntax is extremely context-heavy and has a huge number of exceptions and special cases). Pragmatically though, we might be able to live with the approximate solution we already use for~
.
But: while we can argue about the interface and come up with pros and cons for several approaches (e.g. "history command" vs "manipulation during interactive search"), I still have a hard time coming up with a simple but robust implementation of actually deleting a command from all the running PyCmd instances -- deleting from just the current instance is not enough, other PyCmd instances will just write the command back to the history file!
Some implementation ideas:
use an additional "daemon" executable to synchronize all running instances of PyCmd (this is what e.g. the fish shell is doing).
python PyCmd.py
?)AF_UNIX
is not supported in Python)write "requests" for command deletions to a dedicated file (say, %APPDATA%\PyCmd\history_delete):
<PID> <command-to-delete>
lines inside, for each <PID>
of running PyCmd instances except the current one (this is trickier than it sounds, PyCmd.exe is relatively easy but what do we do for PyCmd instances that are started via python PyCmd.py
?)This is a reasonable interface, but I am hoping we can work out (possibly: in addition) something more user-friendly/interactive interface.
I actually agree with you. When typing the idea I already thought to myself that implementing an internal 'history' command would be too much off the road somehow.
Ideas on how to implement this (ideally: in a simple way) are welcome
As silly as possible.. you asked for it 😊: Currently the history only gets updated on disc when pressing ENTER (and two more cases with ESC and CTRL+G?). Would it be too expensive resp. slow to also always update the history in memory (thus back from disc) when navigating/searching it? The current 'update_history(_to_file)' function doesn't lock the file, so I guess a new 'update_history_from_file' function wouldn't require a file lock as well, since you usually can't type into two command lines (PyCmd instances) at the same time. If this wouldn't kill the performance it would also add the advantage that all running instances would receive new commands entered into another instance. I mean without restarting the other instances. Of course it doesn't happen every day, but sometimes I miss newly entered commands in other running instances.. and then immediately remember that I would have to restart the instance in order to update the history.
Forget the idea about inheriting new history entries from other running instances. Neither fish nor bash behave like that. It would be too tricky and lead to unwanted behavior anyway.
You are making some very good points here -- thank you for looking into this topic!
I looked over PyCmd's "history update" mechanism (which was implemented many years ago) and I think we can indeed come up with a simpler implementation for deleting commands, along the lines that you sketched: when the deletion is triggered (say, Ctrl-Alt-K during history search) we remove the command from the state.history.list
of the current PyCmd AND delete it from the history file as well. This would of course not delete it from the state.history.list
of the other running PyCmd instances, but I think we can live with this. Some additional things to consider:
If you want to experiment with implementing this feature (it's not trivial, but hopefully also not too hard) let me know and I will assign this issue to you; if not, I will add this to my TODO list (somewhere near the top actually: this is a feature that I've been wanting to add for a long time but never realized there might be a simple implementation)
As for the live synchronization of the history across running instances: I tried to add this in at some point in the past, but it ended up more confusing than useful; also the other shells don't have this (as you mentioned) so I think we should forget about this (at least for now).
Starting with release 20230829, Ctrl-Alt-K (during editing, filtered search and interactive search) deletes the "current" command from the current session AND the saved history file.
Thanks @ufo for the push and the brainstorming :)
Sometimes it is desirable to delete some earlier command from the history (e.g. it might contain sensitive information, or maybe it's just plain wrong and we don't want it to "pollute" the history).
This action could be triggered by some key combination (Ctrl-Shift-K?) while navigating the history (either via the current paradigm "type filter string, then Up" or possibly during incremental search as proposed by #1).
Implementing this is complicated because it requires cooperation between multiple running PyCmd instances: deleting from the current instance is not enough, as the other instances will still have it and save it in the history file. This is why the only manual workaround is currently to close all PyCmd processes for the current user, then manipulate the %APPDATA%\history file using some editor.
Ideas on how to implement this (ideally: in a simple way) are welcome :smile: