it2 0.2.1__tar.gz → 0.2.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {it2-0.2.1 → it2-0.2.3}/PKG-INFO +1 -1
- {it2-0.2.1 → it2-0.2.3}/pyproject.toml +1 -1
- {it2-0.2.1 → it2-0.2.3}/src/it2/__init__.py +1 -1
- {it2-0.2.1 → it2-0.2.3}/src/it2/commands/app.py +2 -1
- {it2-0.2.1 → it2-0.2.3}/src/it2/commands/profile.py +2 -1
- {it2-0.2.1 → it2-0.2.3}/src/it2/commands/session.py +2 -2
- {it2-0.2.1 → it2-0.2.3}/src/it2/core/session_handler.py +66 -1
- {it2-0.2.1 → it2-0.2.3}/.gitignore +0 -0
- {it2-0.2.1 → it2-0.2.3}/LICENSE +0 -0
- {it2-0.2.1 → it2-0.2.3}/README.md +0 -0
- {it2-0.2.1 → it2-0.2.3}/src/it2/cli.py +0 -0
- {it2-0.2.1 → it2-0.2.3}/src/it2/commands/__init__.py +0 -0
- {it2-0.2.1 → it2-0.2.3}/src/it2/commands/config_commands.py +0 -0
- {it2-0.2.1 → it2-0.2.3}/src/it2/commands/monitor.py +0 -0
- {it2-0.2.1 → it2-0.2.3}/src/it2/commands/shortcuts.py +0 -0
- {it2-0.2.1 → it2-0.2.3}/src/it2/commands/tab.py +0 -0
- {it2-0.2.1 → it2-0.2.3}/src/it2/commands/window.py +0 -0
- {it2-0.2.1 → it2-0.2.3}/src/it2/core/__init__.py +0 -0
- {it2-0.2.1 → it2-0.2.3}/src/it2/core/connection.py +0 -0
- {it2-0.2.1 → it2-0.2.3}/src/it2/core/errors.py +0 -0
- {it2-0.2.1 → it2-0.2.3}/src/it2/utils/__init__.py +0 -0
- {it2-0.2.1 → it2-0.2.3}/src/it2/utils/config.py +0 -0
{it2-0.2.1 → it2-0.2.3}/PKG-INFO
RENAMED
|
@@ -5,6 +5,7 @@ import iterm2
|
|
|
5
5
|
|
|
6
6
|
from ..core.connection import run_command
|
|
7
7
|
from ..core.errors import handle_error
|
|
8
|
+
from ..core.session_handler import get_session_by_id
|
|
8
9
|
|
|
9
10
|
# Theme value mapping for PreferenceKey.THEME
|
|
10
11
|
_THEME_MAP = {
|
|
@@ -105,7 +106,7 @@ async def broadcast_add(
|
|
|
105
106
|
# Verify all sessions exist
|
|
106
107
|
sessions = []
|
|
107
108
|
for sid in session_ids:
|
|
108
|
-
session =
|
|
109
|
+
session = get_session_by_id(app, sid)
|
|
109
110
|
if not session:
|
|
110
111
|
handle_error(f"Session '{sid}' not found", 3)
|
|
111
112
|
sessions.append(session)
|
|
@@ -10,6 +10,7 @@ from rich.table import Table
|
|
|
10
10
|
|
|
11
11
|
from ..core.connection import run_command
|
|
12
12
|
from ..core.errors import handle_error
|
|
13
|
+
from ..core.session_handler import get_session_by_id
|
|
13
14
|
|
|
14
15
|
console = Console()
|
|
15
16
|
|
|
@@ -142,7 +143,7 @@ async def apply(
|
|
|
142
143
|
|
|
143
144
|
# Get target session
|
|
144
145
|
if session:
|
|
145
|
-
target_session =
|
|
146
|
+
target_session = get_session_by_id(app, session)
|
|
146
147
|
if not target_session:
|
|
147
148
|
handle_error(f"Session '{session}' not found", 3)
|
|
148
149
|
else:
|
|
@@ -9,7 +9,7 @@ from rich.table import Table
|
|
|
9
9
|
|
|
10
10
|
from ..core.connection import run_command
|
|
11
11
|
from ..core.errors import handle_error
|
|
12
|
-
from ..core.session_handler import get_session_info, get_target_sessions
|
|
12
|
+
from ..core.session_handler import get_session_by_id, get_session_info, get_target_sessions
|
|
13
13
|
|
|
14
14
|
console = Console()
|
|
15
15
|
|
|
@@ -157,7 +157,7 @@ async def restart(session: str | None, connection: iterm2.Connection, app: iterm
|
|
|
157
157
|
@run_command
|
|
158
158
|
async def focus(session_id: str, connection: iterm2.Connection, app: iterm2.App) -> None:
|
|
159
159
|
"""Focus a specific session."""
|
|
160
|
-
target_session =
|
|
160
|
+
target_session = get_session_by_id(app, session_id)
|
|
161
161
|
if not target_session:
|
|
162
162
|
handle_error(f"Session '{session_id}' not found", 3)
|
|
163
163
|
|
|
@@ -1,9 +1,74 @@
|
|
|
1
1
|
"""Session handling utilities for iTerm2 CLI."""
|
|
2
2
|
|
|
3
|
+
import re
|
|
3
4
|
import sys
|
|
4
5
|
|
|
5
6
|
from iterm2 import App, Session
|
|
6
7
|
|
|
8
|
+
_UUID_PATTERN = r"[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{12}"
|
|
9
|
+
# iTerm2 commonly exposes these aliases:
|
|
10
|
+
# - ITERM_SESSION_ID / TERM_SESSION_ID: w<window>t<tab>p<pane>:<GUID>
|
|
11
|
+
# - session.termid variable: w<window>t<tab>p<pane>.<GUID>
|
|
12
|
+
# Only the GUID portion is the canonical API session identifier.
|
|
13
|
+
_ITERM_SESSION_ID_RE = re.compile(rf"^w\d+t\d+p\d+:(?P<uuid>{_UUID_PATTERN})$")
|
|
14
|
+
_TERMID_RE = re.compile(rf"^w\d+t\d+p\d+\.(?P<uuid>{_UUID_PATTERN})$")
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def normalize_session_id(session_id: str | None) -> str | None:
|
|
18
|
+
"""Normalize session ID aliases to a canonical UUID when possible.
|
|
19
|
+
|
|
20
|
+
Why this exists:
|
|
21
|
+
iTerm2 core builds ``ITERM_SESSION_ID`` in the form
|
|
22
|
+
``w<window>t<tab>p<pane>:<guid>`` (see PTYSession.sessionId), and also
|
|
23
|
+
publishes ``session.termid`` as ``w<window>t<tab>p<pane>.<guid>``.
|
|
24
|
+
However, iTerm2's Python API stores ``Session.session_id`` as only the
|
|
25
|
+
GUID and ``App.get_session_by_id`` does an exact string match against that
|
|
26
|
+
GUID. Passing prefixed aliases directly therefore fails lookup.
|
|
27
|
+
|
|
28
|
+
When this is needed:
|
|
29
|
+
Any time we accept user-provided session identifiers (CLI args, env vars,
|
|
30
|
+
script output), because those inputs often come from shell integration
|
|
31
|
+
variables instead of the bare API GUID.
|
|
32
|
+
"""
|
|
33
|
+
if session_id is None:
|
|
34
|
+
return None
|
|
35
|
+
|
|
36
|
+
if session_id in {"active", "all"}:
|
|
37
|
+
return session_id
|
|
38
|
+
|
|
39
|
+
match = _ITERM_SESSION_ID_RE.match(session_id)
|
|
40
|
+
if match:
|
|
41
|
+
return match.group("uuid")
|
|
42
|
+
|
|
43
|
+
match = _TERMID_RE.match(session_id)
|
|
44
|
+
if match:
|
|
45
|
+
return match.group("uuid")
|
|
46
|
+
|
|
47
|
+
return session_id
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def get_session_by_id(app: App, session_id: str | None) -> Session | None:
|
|
51
|
+
"""Get a session by ID while accepting common iTerm2 alias formats.
|
|
52
|
+
|
|
53
|
+
This centralizes the ID-shape mismatch between shell-facing identifiers and
|
|
54
|
+
API-facing identifiers so command handlers can call one safe lookup path.
|
|
55
|
+
"""
|
|
56
|
+
if session_id is None:
|
|
57
|
+
return None
|
|
58
|
+
|
|
59
|
+
normalized = normalize_session_id(session_id)
|
|
60
|
+
if normalized is None:
|
|
61
|
+
return None
|
|
62
|
+
|
|
63
|
+
session = app.get_session_by_id(normalized)
|
|
64
|
+
if session:
|
|
65
|
+
return session
|
|
66
|
+
|
|
67
|
+
# Fallback for unexpected future formats where normalization is too strict.
|
|
68
|
+
if normalized != session_id:
|
|
69
|
+
return app.get_session_by_id(session_id)
|
|
70
|
+
return None
|
|
71
|
+
|
|
7
72
|
|
|
8
73
|
async def get_target_sessions(
|
|
9
74
|
app: App, session_id: str | None = None, all_sessions: bool = False
|
|
@@ -28,7 +93,7 @@ async def get_target_sessions(
|
|
|
28
93
|
|
|
29
94
|
if session_id and session_id != "active":
|
|
30
95
|
# Get specific session by ID
|
|
31
|
-
session =
|
|
96
|
+
session = get_session_by_id(app, session_id)
|
|
32
97
|
if not session:
|
|
33
98
|
print(f"Error: Session '{session_id}' not found", file=sys.stderr)
|
|
34
99
|
sys.exit(3)
|
|
File without changes
|
{it2-0.2.1 → it2-0.2.3}/LICENSE
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|