diff --git a/nbs/00_core.ipynb b/nbs/00_core.ipynb
index 1436f52..76a785c 100644
--- a/nbs/00_core.ipynb
+++ b/nbs/00_core.ipynb
@@ -74,7 +74,22 @@
"execution_count": null,
"id": "2ddd0b97",
"metadata": {},
- "outputs": [],
+ "outputs": [
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "\u001b[92m11:15:42 - LiteLLM:WARNING\u001b[0m: common_utils.py:979 - litellm: could not pre-load bedrock-runtime response stream shape — Bedrock event-stream decoding will be unavailable. Error: No module named 'botocore'\n"
+ ]
+ },
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "\u001b[92m11:15:42 - LiteLLM:WARNING\u001b[0m: common_utils.py:24 - litellm: could not pre-load sagemaker-runtime response stream shape — SageMaker event-stream decoding will be unavailable. Error: No module named 'botocore'\n"
+ ]
+ }
+ ],
"source": [
"#| hide\n",
"enable_cachy()"
@@ -318,7 +333,15 @@
"id": "b2912805",
"metadata": {},
"source": [
- "## Tmux"
+ "## Terminal history"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "723ba859",
+ "metadata": {},
+ "source": [
+ "The most cross platfrom way is to use tmux"
]
},
{
@@ -435,7 +458,8 @@
"outputs": [],
"source": [
"#| export\n",
- "def get_history(n, pid='current'):\n",
+ "def get_hist_tmux(n, pid='current'):\n",
+ " if not os.environ.get('TMUX'): return None\n",
" try:\n",
" if pid=='current': return get_pane(n)\n",
" if pid=='all': return get_panes(n)\n",
@@ -443,6 +467,60 @@
" except subprocess.CalledProcessError: return None"
]
},
+ {
+ "cell_type": "markdown",
+ "id": "6a05b3f9",
+ "metadata": {},
+ "source": [
+ "We can also use the terminal app's API to get the history. Here is how to do it for Apple Terminal and iTerm.app.\n",
+ "\n",
+ "Due to macOS sandboxing, osascript can only script the terminal app it was executed from and cannot access other terminal apps. So, the easiest way to test this is to run these commands manually in the terminal:\n",
+ "\n",
+ "```bash\n",
+ "osascript -e 'tell application \"Terminal\" to get the contents of the selected tab of the front window'\n",
+ "osascript -e 'tell application id \"com.googlecode.iterm2\" to get text of current session of current tab of current window'\n",
+ "```"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "0eda0216",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "#| export\n",
+ "def get_hist_osa(n, pid=''):\n",
+ " script = ({\n",
+ " 'Apple_Terminal':'tell application \"Terminal\" to get the contents of the selected tab of the front window',\n",
+ " 'iTerm.app':'tell application id \"com.googlecode.iterm2\" to get text of current session of current tab of current window',\n",
+ " }).get(os.getenv('TERM_PROGRAM'))\n",
+ " if not script: return None\n",
+ " return \"\\n\".join(co(['osascript', '-e', script], text=True).splitlines()[:n])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "e6e9b4b5",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "#get_hist_osa(3)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "5344a2bd",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "#| export\n",
+ "def get_history(n, pid='current'):\n",
+ " return get_hist_tmux(n, pid) or get_hist_osa(n)"
+ ]
+ },
{
"cell_type": "markdown",
"id": "fc100d13",
@@ -930,11 +1008,10 @@
" ctxt = '' if skip_system else _sys_info()\n",
"\n",
" # Get tmux history if in a tmux session\n",
- " if os.environ.get('TMUX'):\n",
- " if opts.history_lines is None or opts.history_lines < 0:\n",
- " opts.history_lines = tmux_history_lim()\n",
- " history = get_history(opts.history_lines, pid)\n",
- " if history: ctxt += f'\\n{history}\\n'\n",
+ " if opts.history_lines is None or opts.history_lines < 0:\n",
+ " opts.history_lines = tmux_history_lim()\n",
+ " history = get_history(opts.history_lines, pid)\n",
+ " if history: ctxt += f'\\n{history}\\n'\n",
"\n",
" # Read from redirect stdin if available\n",
" if not sys.stdin.isatty() and not IN_NOTEBOOK:\n",
diff --git a/shell_sage/_modidx.py b/shell_sage/_modidx.py
index 8f7aa6d..c464ad1 100644
--- a/shell_sage/_modidx.py
+++ b/shell_sage/_modidx.py
@@ -16,6 +16,8 @@
'shell_sage.core._sys_info': ('core.html#_sys_info', 'shell_sage/core.py'),
'shell_sage.core.extract': ('core.html#extract', 'shell_sage/core.py'),
'shell_sage.core.extract_cf': ('core.html#extract_cf', 'shell_sage/core.py'),
+ 'shell_sage.core.get_hist_osa': ('core.html#get_hist_osa', 'shell_sage/core.py'),
+ 'shell_sage.core.get_hist_tmux': ('core.html#get_hist_tmux', 'shell_sage/core.py'),
'shell_sage.core.get_history': ('core.html#get_history', 'shell_sage/core.py'),
'shell_sage.core.get_opts': ('core.html#get_opts', 'shell_sage/core.py'),
'shell_sage.core.get_pane': ('core.html#get_pane', 'shell_sage/core.py'),
diff --git a/shell_sage/core.py b/shell_sage/core.py
index b27056d..0fc7b3d 100644
--- a/shell_sage/core.py
+++ b/shell_sage/core.py
@@ -4,8 +4,8 @@
# %% auto #0
__all__ = ['console', 'print', 'sp', 'ssp', 'default_cfg', 'tools', 'sps', 'log_path', 'get_pane', 'get_panes',
- 'tmux_history_lim', 'get_history', 'get_opts', 'with_permission', 'get_sage', 'get_res', 'Log', 'mk_db',
- 'main', 'extract_cf', 'extract']
+ 'tmux_history_lim', 'get_hist_tmux', 'get_hist_osa', 'get_history', 'get_opts', 'with_permission',
+ 'get_sage', 'get_res', 'Log', 'mk_db', 'main', 'extract_cf', 'extract']
# %% ../nbs/00_core.ipynb #d7c5634a
from contextlib import contextmanager
@@ -162,13 +162,27 @@ def tmux_history_lim():
# %% ../nbs/00_core.ipynb #0d70591e
-def get_history(n, pid='current'):
+def get_hist_tmux(n, pid='current'):
+ if not os.environ.get('TMUX'): return None
try:
if pid=='current': return get_pane(n)
if pid=='all': return get_panes(n)
return get_pane(n, pid)
except subprocess.CalledProcessError: return None
+# %% ../nbs/00_core.ipynb #0eda0216
+def get_hist_osa(n, pid=''):
+ script = ({
+ 'Apple_Terminal':'tell application "Terminal" to get the contents of the selected tab of the front window',
+ 'iTerm.app':'tell application id "com.googlecode.iterm2" to get text of current session of current tab of current window',
+ }).get(os.getenv('TERM_PROGRAM'))
+ if not script: return None
+ return "\n".join(co(['osascript', '-e', script], text=True).splitlines()[:n])
+
+# %% ../nbs/00_core.ipynb #5344a2bd
+def get_history(n, pid='current'):
+ return get_hist_tmux(n, pid) or get_hist_osa(n)
+
# %% ../nbs/00_core.ipynb #0dcbb503
default_cfg = asdict(ShellSageConfig())
def get_opts(**opts):
@@ -295,11 +309,10 @@ async def main(
ctxt = '' if skip_system else _sys_info()
# Get tmux history if in a tmux session
- if os.environ.get('TMUX'):
- if opts.history_lines is None or opts.history_lines < 0:
- opts.history_lines = tmux_history_lim()
- history = get_history(opts.history_lines, pid)
- if history: ctxt += f'\n{history}\n'
+ if opts.history_lines is None or opts.history_lines < 0:
+ opts.history_lines = tmux_history_lim()
+ history = get_history(opts.history_lines, pid)
+ if history: ctxt += f'\n{history}\n'
# Read from redirect stdin if available
if not sys.stdin.isatty() and not IN_NOTEBOOK: