""".. versionadded:: 0.1.0
Control iTerm using JXA-like syntax.
"""
from typing import Union
import AppKit
from PyXA import XABaseScriptable, XABase
from PyXA.XAProtocols import XACloseable, XADeletable, XAPrintable, XASelectable
[docs]
class XAiTermApplication(XABaseScriptable.XASBApplication):
"""A class for managing and interacting with iTerm.app.
.. versionadded:: 0.1.0
"""
def __init__(self, properties):
super().__init__(properties)
self.xa_wcls = XAiTermWindow
@property
def current_window(self) -> "XAiTermWindow":
"""The frontmost window."""
return self._new_element(self.xa_scel.current_window(), XAiTermWindow)
@current_window.setter
def current_window(self, current_window: "XAiTermWindow"):
self.set_property("currentWindow", current_window.xa_elem)
@property
def name(self) -> str:
"""The name of the application."""
return self.xa_scel.name()
@property
def frontmost(self) -> bool:
"""Whether iTerm is the active application."""
return self.xa_scel.frontmost()
@property
def version(self) -> str:
"""The version of iTerm.app."""
return self.xa_scel.version()
[docs]
def create_window(
self, profile: Union[str, None] = None, command: Union[str, None] = None
) -> "XAiTermWindow":
"""Creates a new window with the given profile, executing the specified command upon the window's creation.
:param profile: The profile to initialize the window with, defaults to None (default profile)
:type profile: Union[str, None], optional
:param command: The command to execute, defaults to None
:type command: Union[str, None], optional
:return: The newly created window object
:rtype: XAiTermWindow
.. versionadded:: 0.1.0
"""
if profile is None:
window = self.xa_scel.createWindowWithDefaultProfileCommand_(command)
else:
window = self.xa_scel.createWindowWithProfile_command_(profile, command)
return self._new_element(window, XAiTermWindow)
[docs]
def create_hotkey_window(
self, profile: Union[str, None] = None
) -> "XAiTermHotkeyWindow":
"""Creates a new hotkey window with the given profile.
:param profile: The profile to initialize the window with, defaults to None
:type profile: Union[str, None], optional
:return: The newly created hotkey window object
:rtype: XAiTermHotkeyWindow
.. versionadded:: 0.1.0
"""
window = self.xa_scel.createHotkeyWindowWithProfile_(profile)
return self._new_element(window, XAiTermHotkeyWindow)
[docs]
def request_cookie_and_key(self, app: str) -> str:
"""Requests a Python API cookie for the specified application.
:param app: The app to retrieve an API cookie for
:type app: str
:return: The API cookie
:rtype: str
.. versionadded:: 0.1.0
"""
return self.xa_scel.requestCookieAndKeyForAppNamed_(app)
[docs]
def launch_api_script(
self, script_name: str, arguments: Union[list[str], None] = None
):
"""Launches an API script by name, providing it with the given arguments.
:param script_name: The name of the script to launch
:type script_name: str
:param arguments: The arguments to pass to the script, defaults to None
:type arguments: Union[list[str], None], optional
.. versionadded:: 0.1.0
"""
if arguments is None:
arguments = []
self.xa_scel.launchAPIScriptNamed_arguments_(script_name, arguments)
[docs]
def invoke_api_expression(self, expression: str):
"""Invokes an expression, such as a registered function.
:param expression: The expression to invoke
:type expression: str
.. versionadded:: 0.1.0
"""
self.xa_scel.invokeAPIExpression_(expression)
[docs]
class XAiTermWindow(
XABaseScriptable.XASBWindow, XABase.XAObject, XASelectable, XACloseable
):
"""A window of iTerm.app.
.. versionadded:: 0.1.0
"""
def __init__(self, properties):
super().__init__(properties)
if self.is_hotkey_window:
self.__class__ = XAiTermHotkeyWindow
@property
def alternate_identifier(self) -> str:
"""The alternate unique identifier of the session."""
return self.xa_elem.alternateIdentifier()
@property
def frontmost(self) -> bool:
"""Whether the window is currently the frontmost iTerm window."""
return self.xa_elem.frontmost()
@frontmost.setter
def frontmost(self, frontmost: bool):
self.set_property("frontmost", frontmost)
@property
def current_tab(self) -> "XAiTermTab":
"""The currently selected tab."""
return self._new_element(self.xa_elem.currentTab(), XAiTermTab)
@current_tab.setter
def current_tab(self, current_tab: "XAiTermTab"):
self.set_property("currentTab", current_tab.xa_elem)
@property
def current_session(self) -> "XAiTermSession":
"""The current session in a window."""
return self._new_element(self.xa_elem.currentSession(), XAiTermSession)
@current_session.setter
def current_session(self, current_session: "XAiTermSession"):
self.set_property("currentSession", current_session.xa_elem)
@property
def is_hotkey_window(self) -> bool:
"""Whether the window is a hotkey window."""
return self.xa_elem.isHotkeyWindow()
@is_hotkey_window.setter
def is_hotkey_window(self, is_hotkey_window: bool):
self.set_property("isHotkeyWindow", is_hotkey_window)
@property
def hotkey_window_profile(self) -> str:
"""If the window is a hotkey window, this gives the name of the profile that created the window."""
return self.xa_elem.hotkeyWindowProfile()
@hotkey_window_profile.setter
def hotkey_window_profile(self, hotkey_window_profile: str):
self.set_property("hotkeyWindowProfile", hotkey_window_profile)
@property
def position(self) -> tuple[int, int]:
"""The position of the window, relative to the upper left corner of the screen."""
return self.xa_elem.position()
@position.setter
def position(self, position: tuple[int, int]):
self.set_property("position", position)
[docs]
def create_tab(
self, profile: Union[str, None] = None, command: Union[str, None] = None
):
"""Creates a new tab with the given profile, executing the specified command upon the tab's creation.
:param profile: The name of the profile to assign to the tab, if any, defaults to None (default profile)
:type profile: Union[str, None], optional
:param command: The command to run in the tab, if any, defaults to None
:type command: Union[str, None], optional
"""
if profile is None:
self.xa_elem.createTabWithDefaultProfileCommand_(command)
else:
self.xa_elem.createTabWithProfile_command_(profile, command)
[docs]
def close(self):
"""Closes the window.
.. versionadded:: 0.1.0
"""
self.xa_elem.close()
[docs]
class XAiTermHotkeyWindow(XAiTermWindow):
"""A hotkey window of iTerm.app.
.. versionadded:: 0.1.0
"""
def __init__(self, properties):
super().__init__(properties)
[docs]
def reveal_hotkey_window(self):
"""Reveals the hotkey window.
.. versionadded:: 0.1.0
"""
self.xa_elem.revealHotkeyWindow()
[docs]
def hide_hotkey_window(self):
"""Hides the hotkey window.
.. versionadded:: 0.1.0
"""
self.xa_elem.hideHotkeyWindow()
[docs]
def toggle_hotkey_window(self):
"""Toggles the hotkey window.
.. versionadded:: 0.1.0
"""
self.xa_elem.toggleHotkeyWindow()
[docs]
class XAiTermTab(XABase.XAObject, XACloseable, XASelectable):
"""A tab of iTerm.app.
.. versionadded:: 0.1.0
"""
def __init__(self, properties):
super().__init__(properties)
@property
def current_session(self) -> "XAiTermSession":
"""The current session in a tab."""
return self._new_element(self.xa_elem.currentSession(), XAiTermSession)
@current_session.setter
def current_session(self, current_session: "XAiTermSession"):
self.set_property("currentSession", current_session.xa_elem)
@property
def index(self) -> int:
"""Index of tab in parent tab view control."""
return self.xa_elem.index()
@index.setter
def index(self, index: int):
self.set_property("index", index)
[docs]
def close(self):
"""Closes the tab.
.. versionadded:: 0.1.0
"""
self.xa_elem.close()
[docs]
def move_to(self, window: XAiTermWindow):
self.xa_elem.moveTo_(window.xa_elem)
[docs]
class XAiTermSession(XABase.XAObject, XACloseable, XASelectable):
"""A session of iTerm.app.
.. versionadded:: 0.1.0
"""
def __init__(self, properties):
super().__init__(properties)
@property
def id(self) -> str:
"""The unique identifier of the session."""
return self.xa_elem.id()
@property
def is_processing(self) -> bool:
"""Whether the session is currently processing."""
return self.xa_elem.isProcessing()
@is_processing.setter
def is_processing(self, is_processing: bool):
self.set_property("isProcessing", is_processing)
@property
def is_at_shell_prompt(self) -> bool:
"""Whether the terminal is at the shell prompt."""
return self.xa_elem.isAtShellPrompt()
@is_at_shell_prompt.setter
def is_at_shell_prompt(self, is_at_shell_prompt: bool):
self.set_property("isAtShellPrompt", is_at_shell_prompt)
@property
def columns(self) -> int:
"""The number of columns in the terminal window."""
return self.xa_elem.columns()
@columns.setter
def columns(self, columns: int):
self.set_property("columns", columns)
@property
def rows(self) -> int:
"""The number of rows in the terminal window."""
return self.xa_elem.rows()
@rows.setter
def rows(self, rows: int):
self.set_property("rows", rows)
@property
def tty(self) -> str:
"""The current TTY."""
return self.xa_elem.tty()
@property
def contents(self) -> str:
"""The currently visible contents of the session."""
return self.xa_elem.contents()
@contents.setter
def contents(self, contents: str):
self.set_property("contents", contents)
@property
def text(self) -> str:
"""The currently visible contents of the session."""
return self.xa_elem.text()
@property
def color_preset(self) -> str:
"""The color preset of the session."""
return self.xa_elem.colorPreset()
@color_preset.setter
def color_preset(self, color_preset: str):
self.set_property("colorPreset", color_preset)
@property
def background_color(self) -> XABase.XAColor:
return XABase.XAColor(self.xa_elem.backgroundColor())
@background_color.setter
def background_color(self, background_color: XABase.XAColor):
self.set_property("backgroundColor", background_color.xa_elem)
@property
def bold_color(self) -> XABase.XAColor:
return XABase.XAColor(self.xa_elem.boldColor())
@bold_color.setter
def bold_color(self, bold_color: XABase.XAColor):
self.set_property("boldColor", bold_color.xa_elem)
@property
def cursor_color(self) -> XABase.XAColor:
return XABase.XAColor(self.xa_elem.cursorColor())
@cursor_color.setter
def cursor_color(self, cursor_color: XABase.XAColor):
self.set_property("cursorColor", cursor_color.xa_elem)
@property
def cursor_text_color(self) -> XABase.XAColor:
return XABase.XAColor(self.xa_elem.cursorTextColor())
@cursor_text_color.setter
def cursor_text_color(self, cursor_text_color: XABase.XAColor):
self.set_property("cursorTextColor", cursor_text_color.xa_elem)
@property
def foreground_color(self) -> XABase.XAColor:
return XABase.XAColor(self.xa_elem.foregroundColor())
@foreground_color.setter
def foreground_color(self, foreground_color: XABase.XAColor):
self.set_property("foregroundColor", foreground_color.xa_elem)
@property
def selected_text_color(self) -> XABase.XAColor:
return XABase.XAColor(self.xa_elem.selectedTextColor())
@selected_text_color.setter
def selected_text_color(self, selected_text_color: XABase.XAColor):
self.set_property("selectedTextColor", selected_text_color.xa_elem)
@property
def selection_color(self) -> XABase.XAColor:
return XABase.XAColor(self.xa_elem.selectionColor())
@selection_color.setter
def selection_color(self, selection_color: XABase.XAColor):
self.set_property("selectionColor", selection_color.xa_elem)
@property
def ansi_black_color(self) -> XABase.XAColor:
return XABase.XAColor(self.xa_elem.ANSIBlackColor())
@ansi_black_color.setter
def ansi_black_color(self, ansi_black_color: XABase.XAColor):
self.set_property("ANSIBlackColor", ansi_black_color.xa_elem)
@property
def ansi_red_color(self) -> XABase.XAColor:
return XABase.XAColor(self.xa_elem.ANSIRedColor())
@ansi_red_color.setter
def ansi_black_color(self, ansi_red_color: XABase.XAColor):
self.set_property("ANSIRedColor", ansi_red_color.xa_elem)
@property
def ansi_green_color(self) -> XABase.XAColor:
return XABase.XAColor(self.xa_elem.ANSIGreenColor())
@ansi_green_color.setter
def ansi_green_color(self, ansi_green_color: XABase.XAColor):
self.set_property("ANSIGreenColor", ansi_green_color.xa_elem)
@property
def ansi_yellow_color(self) -> XABase.XAColor:
return XABase.XAColor(self.xa_elem.ANSIYellowColor())
@ansi_yellow_color.setter
def ansi_yellow_color(self, ansi_yellow_color: XABase.XAColor):
self.set_property("ANSIYellowColor", ansi_yellow_color.xa_elem)
@property
def ansi_blue_color(self) -> XABase.XAColor:
return XABase.XAColor(self.xa_elem.ANSIBlueColor())
@ansi_blue_color.setter
def ansi_blue_color(self, ansi_blue_color: XABase.XAColor):
self.set_property("ANSIBlueColor", ansi_blue_color.xa_elem)
@property
def ansi_magenta_color(self) -> XABase.XAColor:
return XABase.XAColor(self.xa_elem.ANSIMagentaColor())
@ansi_magenta_color.setter
def ansi_magenta_color(self, ansi_magenta_color: XABase.XAColor):
self.set_property("ANSIMagentaColor", ansi_magenta_color.xa_elem)
@property
def ansi_cyan_color(self) -> XABase.XAColor:
return XABase.XAColor(self.xa_elem.ANSICyanColor())
@ansi_cyan_color.setter
def ansi_cyan_color(self, ansi_cyan_color: XABase.XAColor):
self.set_property("ANSICyanColor", ansi_cyan_color.xa_elem)
@property
def ansi_white_color(self) -> XABase.XAColor:
return XABase.XAColor(self.xa_elem.ANSIWhiteColor())
@ansi_white_color.setter
def ansi_white_color(self, ansi_white_color: XABase.XAColor):
self.set_property("ANSIWhiteColor", ansi_white_color.xa_elem)
@property
def ansi_bright_black_color(self) -> XABase.XAColor:
return XABase.XAColor(self.xa_elem.ANSIBrightBlackColor())
@ansi_bright_black_color.setter
def ansi_bright_black_color(self, ansi_bright_black_color: XABase.XAColor):
self.set_property("ANSIBrightBlackColor", ansi_bright_black_color.xa_elem)
@property
def ansi_bright_red_color(self) -> XABase.XAColor:
return XABase.XAColor(self.xa_elem.ANSIBrightRedColor())
@ansi_bright_red_color.setter
def ansi_bright_red_color(self, ansi_bright_red_color: XABase.XAColor):
self.set_property("ANSIBrightRedColor", ansi_bright_red_color.xa_elem)
@property
def ansi_bright_green_color(self) -> XABase.XAColor:
return XABase.XAColor(self.xa_elem.ANSIBrightGreenColor())
@ansi_bright_green_color.setter
def ansi_bright_green_color(self, ansi_bright_green_color: XABase.XAColor):
self.set_property("ANSIBrightGreenColor", ansi_bright_green_color.xa_elem)
@property
def ansi_bright_yellow_color(self) -> XABase.XAColor:
return XABase.XAColor(self.xa_elem.ANSIBrightYellowColor())
@ansi_bright_yellow_color.setter
def ansi_bright_yellow_color(self, ansi_bright_yellow_color: XABase.XAColor):
self.set_property("ANSIBrightYellowColor", ansi_bright_yellow_color.xa_elem)
@property
def ansi_bright_blue_color(self) -> XABase.XAColor:
return XABase.XAColor(self.xa_elem.ANSIBrightBlueColor())
@ansi_bright_blue_color.setter
def ansi_bright_blue_color(self, ansi_bright_blue_color: XABase.XAColor):
self.set_property("ANSIBrightBlueColor", ansi_bright_blue_color.xa_elem)
@property
def ansi_bright_magenta_color(self) -> XABase.XAColor:
return XABase.XAColor(self.xa_elem.ANSIBrightMagentaColor())
@ansi_bright_magenta_color.setter
def ansi_bright_magenta_color(self, ansi_bright_magenta_color: XABase.XAColor):
self.set_property("ANSIBrightMagentaColor", ansi_bright_magenta_color.xa_elem)
@property
def ansi_bright_cyan_color(self) -> XABase.XAColor:
return XABase.XAColor(self.xa_elem.ANSIBrightCyanColor())
@ansi_bright_cyan_color.setter
def ansi_bright_cyan_color(self, ansi_bright_cyan_color: XABase.XAColor):
self.set_property("ANSIBrightCyanColor", ansi_bright_cyan_color.xa_elem)
@property
def ansi_bright_white_color(self) -> XABase.XAColor:
return XABase.XAColor(self.xa_elem.ANSIBrightWhiteColor())
@ansi_bright_white_color.setter
def ansi_bright_white_color(self, ansi_bright_white_color: XABase.XAColor):
self.set_property("ANSIBrightWhiteColor", ansi_bright_white_color.xa_elem)
@property
def underline_color(self) -> XABase.XAColor:
return XABase.XAColor(self.xa_elem.underlineColor())
@underline_color.setter
def underline_color(self, underline_color: XABase.XAColor):
self.set_property("underlineColor", underline_color.xa_elem)
@property
def use_underline_color(self) -> bool:
"""Whether to use a dedicated color for underlining."""
return self.xa_elem.useUnderlineColor()
@use_underline_color.setter
def use_underline_color(self, use_underline_color: bool):
self.set_property("useUnderlineColor", use_underline_color)
@property
def background_image(self) -> str:
"""The path of the background image file."""
return self.xa_elem.backgroundImage()
@background_image.setter
def background_image(self, background_image: str):
self.set_property("backgroundImage", background_image)
@property
def name(self) -> str:
"""The name of the session."""
return self.xa_elem.name()
@name.setter
def name(self, name: str):
self.set_property("name", name)
@property
def transparency(self) -> float:
"""The transparency of the session window."""
return self.xa_elem.transparency()
@transparency.setter
def transparency(self, transparency: float):
self.set_property("transparency", transparency)
@property
def unique_id(self) -> str:
"""The unique identifier of the session."""
return self.xa_elem.uniqueID()
@property
def profile_name(self) -> str:
"""The session's profile name."""
return self.xa_elem.profileName()
@property
def answerback_string(self) -> str:
"""ENQ Answerback string."""
return self.xa_elem.answerbackString()
@answerback_string.setter
def answerback_string(self, answerback_string: str):
self.set_property("answerbackString", answerback_string)
[docs]
def split_vertically(
self, profile: Union[str, None] = None, command: Union[str, None] = None
):
"""Splits the session vertically, instantiating a new session with the specified profile.
:param profile: The profile to instantiate the new session with, defaults to None (current profile)
:type profile: Union[str, None], optional
:param command: The command to run in the newly created session upon its creation, defaults to None
:type command: Union[str, None], optional
.. versionadded:: 0.1.0
"""
if profile is None:
self.xa_elem.splitVerticallyWithSameProfileCommand_(command)
else:
self.xa_elem.splitVerticallyWithProfile_command_(profile, command)
[docs]
def split_vertically_with_default_profile(self, command: Union[str, None]):
"""Splits the session vertically, instantiating a new session with the default profile.
:param command: The command to run in the newly created session upon its creation, defaults to None
:type command: Union[str, None]
.. versionadded:: 0.1.0
"""
self.xa_elem.splitVerticallyWithDefaultProfileCommand_(command)
[docs]
def split_horizontally(
self, profile: Union[str, None] = None, command: Union[str, None] = None
):
"""Splits the session horizontally, instantiating a new session with the specified profile.
:param profile: The profile to instantiate the new session with, defaults to None (current profile)
:type profile: Union[str, None], optional
:param command: The command to run in the newly created session upon its creation, defaults to None
:type command: Union[str, None], optional
.. versionadded:: 0.1.0
"""
if profile is None:
self.xa_elem.splitHorizontallyWithSameProfileCommand_(command)
else:
self.xa_elem.splitHorizontallyWithProfile_command_(profile, command)
[docs]
def split_horizontally_with_default_profile(self, command: Union[str, None] = None):
"""Splits the session horizontally, instantiating a new session with the default profile.
:param command: The command to run in the newly created session upon its creation, defaults to None
:type command: Union[str, None]
.. versionadded:: 0.1.0
"""
self.xa_elem.splitHorizontallyWithDefaultProfileCommand_(command)
[docs]
def variable(self, variable_name: str) -> str:
"""Returns the value of a session variable with the given name.
:param variable_name: The name of the variable to retrieve the value on
:type variable_name: str
:return: The value of the variable
:rtype: str
.. versionadded:: 0.1.0
"""
return self.xa_elem.variableNamed_(variable_name)
[docs]
def set_variable(self, variable_name: str, value: str) -> str:
"""Sets the value of a session variable.
:param variable_name: The name of the variable to set
:type variable_name: str
:param value: The value to give the variable
:type value: str
:return: The new value of the variable
:rtype: str
.. versionadded:: 0.1.0
"""
return self.xa_elem.setVariableNamed_to_(variable_name, value)
[docs]
def write(
self,
text: Union[str, None] = None,
file: Union[XABase.XAPath, str, None] = None,
add_newline: bool = True,
):
"""Writes a string or file contents to the session.
:param text: The text to input into the session, defaults to None
:type text: Union[str, None], optional
:param file: The file whose contents to input into the session, defaults to None
:type file: Union[XABase.XAPath, str, None], optional
:param add_newline: Whether to add a new line after inputting the specified content, defaults to True
:type add_newline: bool, optional
.. versionadded:: 0.1.0
"""
if isinstance(file, str):
file = XABase.XAPath(str)
if file is None:
self.xa_elem.writeContentsOfFile_text_newline_(None, text, add_newline)
else:
self.xa_elem.writeContentsOfFile_text_newline_(
file.xa_elem, text, add_newline
)
[docs]
def close(self):
"""Closes the session.
.. versionadded:: 0.1.0
"""
self.xa_elem.close()