magicant / yash

Yet another shell
http://magicant.github.io/yash/
GNU General Public License v2.0
346 stars 30 forks source link

Very quick attempt at not re-reading history before each prompt. #40

Closed vext01 closed 11 months ago

vext01 commented 11 months ago

This is a quick attempt to address one of the suggestions for https://github.com/magicant/yash/issues/25.

I was thinking of adding two options to change the shell's behavior. The first option can be used to disable the shell from reading new commands from the history file written by other shell instances. The second option makes the shell write the history when the shell exits rather than each time a new command is entered.

For now, I'm considering adding only the first option rather than implementing the both options at once.

This implements the first option only. Is this the kind of thing we want?

If we like this, I think we'd also want a builtin and/or bindable to force reread the history, for those instances where you really do want the history from another shell.

(I notice that you are already using advisory locking on the history file, so you could probably implement something better, where history from other shells is inherited immediately, but the current shell's history are prioritised. The change here however is much simpler)

What do you think?

magicant commented 11 months ago

Thank you for trying to do something, but I have to say that addressing this issue is far harder than it may seem. I tried to implement a similar option myself about two years ago and then gave up.

The current design principle of yash's history is that all shell sessions share the same in-memory copy of the history file. This ensures the integrity of the history saved in the file. If sessions kept different in-memory history data, it would be much more difficult for each session to interact with the file without disturbing other session's interaction with the file.

Based on the principle, any access to the history file is designed to be done in the following manner:

  1. The shell acquires an advisory lock for the file.
  2. The shell reads from the file any unread updates that have been made by other sessions. In this step, if the revision of the file has been changed since the last sync, the shell discards the whole in-memory history and reloads everything from the file to make everything in sync. Otherwise, the shell reads only new entries appended to the file since the last sync.
  3. If the history file contains too many lines compared with an expected size inferred from $HISTSIZE, the shell refreshes the file, that is, the shell clears the file and rewrites the whole in-memory history back to the file, effectively performing garbage collection in the file. During the rewrite to the file, the shell updates the revision number written in the file header to tell other sessions that the file has been refreshed.
  4. The shell writes a new entry to the file, if any.
  5. The shell releases the lock.

So, a simple approach as proposed in this pull request would not be viable as it would break the existing refreshing mechanism described above.

vext01 commented 11 months ago

OK.

I'm finding that having the shared history is absolutely necessary for good-quality shell suggestions, but I'm also finding the behaviour of the up cursor key being frustrating (and potentially dangerous).

Closing this for now then. Thanks