Search code examples
creadlinemacportslibreadlineeditline

How to append history in editline?


I'm trying to add history appension to the MacPorts shell. MacPorts currently uses a bash-like history wherein the history is written after a session is over. This can be problematic if the session should crash, so I'm trying to make the MacPorts shell follow zsh's example. I.e., append each history item to a file as it's executed.

In GNU readline, this functionality is trivial with the function append_history. However, MacPorts relies on Apple's editline instead. The editline library seems to have no equivalent for append_history so I'm a bit lost as to what to do in order to append history to a file. I thought of using good old standard functions like fopen and fprintf, but I realized that editline uses its own encoding for history strings (e.g., the space character is translated to octal \040). MacPorts needs to be compatible with that encoding since editline is used in several places. I assume this encoding is used because whitespace is used as a history delimiter.

I could try to write my own functions to be compatible with this encoding, but that seems fraught with unnecessary difficulties. I feel like I must be missing something. Is there an easy way to append history to a file with editline?


Solution

  • Well, the solution ended up being to use those good old standard functions after all. We also added some file-locking to the mix, just for paranoia's sake:

    s = Tcl_GetString(objv[2]);
    hist_file = fopen(s, "a");
    
    flock(fileno(hist_file), LOCK_EX);
    fprintf(hist_file, "%s\n", current_history()->line);
    flock(fileno(hist_file), LOCK_UN);
    
    fclose(hist_file);
    

    I've explained this in detail here. The file-locking was suggested at the relevant PR. This may not be the final form of the code, but it's what we have so far and it's probably what we'll roll with. If we change it, it will probably be slight.