history pull (#5047)

Co-authored-by: a <aaa@aaa.aaa>
Closes https://github.com/xonsh/xonsh/issues/5044
This commit is contained in:
Andy Kipp 2023-02-08 19:20:01 +06:00 committed by GitHub
parent 6cf78656c7
commit ebb6abd200
Failed to generate hash of commit
5 changed files with 87 additions and 1 deletions

View file

@ -255,6 +255,13 @@ may be useful to share entries between shell sessions. In such a case, one can u
the ``flush`` action to immediately save the session history to disk and make it
accessible from other shell sessions.
``pull`` action
================
Tries to pull the history from parallel sessions and add to the current session.
For example if there are two parallel terminal windows the run of ``history pull``
command from the second terminal window will get the commands from the first terminal.
``clear`` action
================
Deletes the history from the current session up until this point. Later commands

23
news/history_pull.rst Normal file
View file

@ -0,0 +1,23 @@
**Added:**
* Added ``history pull`` command to SQLite history backend to pull the history from parallel sessions and add to the current session.
**Changed:**
* <news item>
**Deprecated:**
* <news item>
**Removed:**
* <news item>
**Fixed:**
* <news item>
**Security:**
* <news item>

View file

@ -130,6 +130,10 @@ class History:
"""
pass
def pull(self, **kwargs):
"""Pull history from other parallel sessions."""
raise NotImplementedError
def flush(self, **kwargs):
"""Flush the history items to disk from a buffer."""
pass

View file

@ -281,6 +281,31 @@ class HistoryAlias(xcli.ArgParserAlias):
return
print(str(hist.sessionid), file=_stdout)
@staticmethod
def pull(show_commands=False, _stdout=None):
"""Pull history from other parallel sessions.
Parameters
----------
show_commands: -c, --show-commands
show pulled commands
"""
hist = XSH.history
if hist.pull.__module__ == "xonsh.history.base":
backend = XSH.env.get("XONSH_HISTORY_BACKEND", "unknown")
print(
f"Pull method is not supported in {backend} history backend.",
file=_stdout,
)
lines_added = hist.pull(show_commands)
if lines_added:
print(f"Added {lines_added} records!", file=_stdout)
else:
print(f"No records found!", file=_stdout)
@staticmethod
def flush(_stdout):
"""Flush the current history to disk"""
@ -428,7 +453,7 @@ class HistoryAlias(xcli.ArgParserAlias):
dest.flush()
self.out("done.")
self.out("Done")
def build(self):
parser = self.create_parser(prog="history")
@ -436,6 +461,7 @@ class HistoryAlias(xcli.ArgParserAlias):
parser.add_command(self.id_cmd, prog="id")
parser.add_command(self.file)
parser.add_command(self.info)
parser.add_command(self.pull)
parser.add_command(self.flush)
parser.add_command(self.off)
parser.add_command(self.on)

View file

@ -204,6 +204,15 @@ def xh_sqlite_delete_items(size_to_keep, filename=None):
return _xh_sqlite_delete_records(c, size_to_keep)
def xh_sqlite_pull(filename, last_pull_time, current_sessionid):
sql = f"SELECT inp FROM xonsh_history WHERE tsb > ? AND sessionid != ? ORDER BY tsb"
params = [last_pull_time, current_sessionid]
with _xh_sqlite_get_conn(filename=filename) as conn:
c = conn.cursor()
c.execute(sql, tuple(params))
return c.fetchall()
def xh_sqlite_wipe_session(sessionid=None, filename=None):
"""Wipe the current session's entries from the database."""
sql = "DELETE FROM xonsh_history WHERE sessionid = ?"
@ -256,6 +265,7 @@ class SqliteHistory(History):
if filename is None:
filename = _xh_sqlite_get_file_name()
self.filename = filename
self.last_pull_time = time.time()
self.gc = SqliteHistoryGC() if gc else None
self._last_hist_inp = None
self.inps = []
@ -345,6 +355,22 @@ class SqliteHistory(History):
data["gc options"] = envs.get("XONSH_HISTORY_SIZE")
return data
def pull(self, show_commands=False):
if not hasattr(XSH.shell.shell, "prompter"):
print(f"Shell type {XSH.shell.shell} is not supported.")
return 0
cnt = 0
for r in xh_sqlite_pull(
self.filename, self.last_pull_time, str(self.sessionid)
):
if show_commands:
print(r[0])
XSH.shell.shell.prompter.history.append_string(r[0])
cnt += 1
self.last_pull_time = time.time()
return cnt
def run_gc(self, size=None, blocking=True):
self.gc = SqliteHistoryGC(wait_for_shell=False, size=size)
if blocking: