-
-
Notifications
You must be signed in to change notification settings - Fork 4.4k
WIP: Implement 'ipython history show [opts]' #13568
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,9 +10,15 @@ | |
|
||
from traitlets.config.application import Application | ||
from .application import BaseIPythonApplication | ||
from traitlets import Bool, Int, Dict | ||
from traitlets import Bool, Int, Dict, Unicode, CaselessStrEnum | ||
from ..utils.io import ask_yes_no | ||
|
||
show_hist_help = """Show recent entries from the IPython history database. | ||
|
||
Limited to the last 1000 unless `--limit=N` is supplied; `--limit=0` or `-1` | ||
prints all entries in the database. | ||
""" | ||
|
||
trim_hist_help = """Trim the IPython history database to the last 1000 entries. | ||
|
||
This actually copies the last 1000 entries to a new database, and then replaces | ||
|
@@ -30,6 +36,123 @@ | |
""" | ||
|
||
|
||
class HistoryShow(BaseIPythonApplication): | ||
description = show_hist_help | ||
limit = Int(1000, help="Number of recent history entries to show.").tag(config=True) | ||
|
||
delimiter = Unicode( | ||
"\t", help="Delimiter for separating the columns of history output." | ||
).tag(config=True) | ||
|
||
header = Bool(False, help="Include a header row in the output.").tag(config=True) | ||
|
||
pretty = Bool( | ||
False, help="Pretty-print the output using IPython.utils.PyColorize." | ||
).tag(config=True) | ||
|
||
colors = CaselessStrEnum( | ||
("Neutral", "NoColor", "LightBG", "Linux"), | ||
default_value="Neutral", | ||
help="Set the color scheme (NoColor, Neutral, Linux, or LightBG).", | ||
).tag(config=True) | ||
Comment on lines
+53
to
+57
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This have changed in 9.0, now we have themes, that are arbitrary strings, the Neutral, CoColor, LightBG, and Linux still exists but are lower case. |
||
|
||
color = CaselessStrEnum( | ||
("Never", "Always", "Auto"), | ||
default_value="Auto", | ||
help="Choose when to display color; requires `--pretty`.", | ||
).tag(config=True) | ||
|
||
flags = Dict( | ||
{ | ||
"L": ( | ||
{"HistoryShow": {"limit": -1}}, | ||
"No limit; show all history entries.", | ||
), | ||
"pretty": ({"HistoryShow": {"pretty": True}}, pretty.help), | ||
"P": ({"HistoryShow": {"pretty": True}}, "An alias for `--pretty`."), | ||
"header": ({"HistoryShow": {"header": True}}, header.help), | ||
"headers": ({"HistoryShow": {"header": True}}, "An alias for `--header`."), | ||
"H": ({"HistoryShow": {"header": True}}, "An alias for `--header`."), | ||
"color-always": ( | ||
{"HistoryShow": {"color": "Always"}}, | ||
"Always output in color (e.g., when piping into `less -R`).", | ||
), | ||
"C": ( | ||
{"HistoryShow": {"color": "Always"}}, | ||
"An alias for `--color-always`.", | ||
), | ||
"color-never": ( | ||
{"HistoryShow": {"color": "Never"}}, | ||
"Never show color, even if the output is a terminal.", | ||
), | ||
} | ||
) | ||
|
||
aliases = Dict( | ||
dict( | ||
l="HistoryShow.limit", | ||
limit="HistoryShow.limit", | ||
d="HistoryShow.delimiter", | ||
delimiter="HistoryShow.delimiter", | ||
header="HistoryShow.header", | ||
pretty="HistoryShow.pretty", | ||
colors="HistoryShow.colors", | ||
color="HistoryShow.color", | ||
) | ||
) | ||
|
||
def start(self): | ||
profile_dir = Path(self.profile_dir.location) | ||
hist_file = profile_dir / "history.sqlite" | ||
con = sqlite3.connect(hist_file) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It hink we can do a |
||
|
||
if not self.limit: | ||
self.limit = -1 | ||
|
||
# Grab the recent history from the current database. | ||
entries = list( | ||
con.execute( | ||
"""SELECT session, line, source, source_raw FROM | ||
history ORDER BY session DESC, line DESC LIMIT ?""", | ||
(self.limit,), | ||
) | ||
) | ||
|
||
# Emulate shell `history` command; newest at bottom | ||
entries.reverse() | ||
|
||
if self.pretty: | ||
import sys | ||
from IPython.utils import PyColorize | ||
Comment on lines
+125
to
+126
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we can import those unconditionally at top of file. |
||
|
||
pyformat = PyColorize.Parser(style=self.colors, parent=self).format | ||
|
||
for entry in entries: | ||
header = f">>> # session {entry[0]}, line {entry[1]}\n" | ||
entry = header + str(entry[3]) | ||
|
||
if ( | ||
sys.stdout.isatty() or self.color == "Always" | ||
) and self.color != "Never": | ||
print(pyformat(entry, out="str")) | ||
else: | ||
# could set self.colors='NoColor' and just use pyformat | ||
# here, too, but this is probably marginally faster | ||
print(entry, "\n") | ||
|
||
else: | ||
if self.header: | ||
print(self.delimiter.join(["session", "line", "source", "source_raw"])) | ||
for entry in entries: | ||
# FIXME: even if you specify `-d,` this is not very | ||
# CSV-friendly, since the outer quote character (single or | ||
# double) depends on whether the history entry itself has | ||
# embedded strings | ||
print(self.delimiter.join([repr(x) for x in entry])) | ||
Comment on lines
+147
to
+151
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think that's fine as is for now. |
||
|
||
con.close() | ||
|
||
|
||
class HistoryTrim(BaseIPythonApplication): | ||
description = trim_hist_help | ||
|
||
|
@@ -144,10 +267,13 @@ class HistoryApp(Application): | |
name = u'ipython-history' | ||
description = "Manage the IPython history database." | ||
|
||
subcommands = Dict(dict( | ||
trim = (HistoryTrim, HistoryTrim.description.splitlines()[0]), | ||
clear = (HistoryClear, HistoryClear.description.splitlines()[0]), | ||
)) | ||
subcommands = Dict( | ||
dict( | ||
show=(HistoryShow, HistoryShow.description.splitlines()[0]), | ||
trim=(HistoryTrim, HistoryTrim.description.splitlines()[0]), | ||
clear=(HistoryClear, HistoryClear.description.splitlines()[0]), | ||
) | ||
) | ||
|
||
def start(self): | ||
if self.subapp is None: | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can inline this directly if you wish, you don't have to rely on a seperate variable. Up to you.