it2api (33202B)
1 #!/usr/bin/env python3.7 2 3 import argparse 4 import asyncio 5 import iterm2 6 import logging 7 import re 8 import sys 9 import traceback 10 11 async def list_sessions(connection, args): 12 a = await iterm2.async_get_app(connection) 13 for w in a.terminal_windows: 14 for t in w.tabs: 15 sessions = t.sessions 16 for s in sessions: 17 print(s.pretty_str(), end='') 18 print("") 19 print("Buried sessions:") 20 for s in a.buried_sessions: 21 print(s.pretty_str(), end='') 22 23 async def show_hierarchy(connection, args): 24 a = await iterm2.async_get_app(connection) 25 print(a.pretty_str()) 26 27 async def send_text(connection, args): 28 a = await iterm2.async_get_app(connection) 29 s = a.get_session_by_id(args.session) 30 await s.async_send_text(args.text) 31 32 async def create_tab(connection, args): 33 a = await iterm2.async_get_app(connection) 34 if args.window is not None: 35 window_id = args.window 36 try: 37 window = next(window for window in a.terminal_windows if window.window_id == window_id) 38 tab = await window.async_create_tab(profile=args.profile, command=args.command, index=args.index) 39 except: 40 print("bad window id {}".format(window_id)) 41 sys.exit(1) 42 else: 43 window = await iterm2.Window.async_create(connection, profile=args.profile, command=args.command) 44 if not window: 45 return 46 tab = window.tabs[0] 47 session = tab.sessions[0] 48 print(session.pretty_str()) 49 50 async def split_pane(connection, args): 51 a = await iterm2.async_get_app(connection) 52 s = a.get_session_by_id(args.session) 53 session = await s.async_split_pane(vertical=args.vertical, before=args.before, profile=args.profile) 54 print(session.pretty_str()) 55 56 async def get_buffer(connection, args): 57 a = await iterm2.async_get_app(connection) 58 s = a.get_session_by_id(args.session) 59 contents = await s.async_get_screen_contents() 60 for i in range(contents.number_of_lines): 61 line = contents.line(i) 62 print(line.string) 63 64 async def get_prompt(connection, args): 65 a = await iterm2.async_get_app(connection) 66 s = a.get_session_by_id(args.session) 67 result = await iterm2.async_get_last_prompt(connection, s.session_id) 68 print("working_directory: \"{}\"".format(result.working_directory)) 69 print("command: \"{}\"".format(result.command)) 70 71 def profile_property_type_map(): 72 map = { 73 "allow_title_reporting": "bool", 74 "allow_title_setting": "bool", 75 "ambiguous_double_width": "bool", 76 "ansi_0_color": "color", 77 "ansi_10_color": "color", 78 "ansi_11_color": "color", 79 "ansi_12_color": "color", 80 "ansi_13_color": "color", 81 "ansi_14_color": "color", 82 "ansi_15_color": "color", 83 "ansi_1_color": "color", 84 "ansi_2_color": "color", 85 "ansi_3_color": "color", 86 "ansi_4_color": "color", 87 "ansi_5_color": "color", 88 "ansi_6_color": "color", 89 "ansi_7_color": "color", 90 "ansi_8_color": "color", 91 "ansi_9_color": "color", 92 "answerback_string": "str", 93 "application_keypad_allowed": "bool", 94 "ascii_anti_aliased": "bool", 95 "ascii_ligatures": "bool", 96 "background_color": "color", 97 "background_image_is_tiled": "bool", 98 "badge_color": "color", 99 "badge_text": "str", 100 "blend": "float", 101 "blink_allowed": "bool", 102 "blinking_cursor": "bool", 103 "blur": "float", 104 "blur_radius": "float", 105 "bm_growl": "bool", 106 "bold_color": "color", 107 "character_encoding": "int", 108 "close_sessions_on_end": "bool", 109 "cursor_boost": "float", 110 "cursor_color": "color", 111 "cursor_guide_color": "color", 112 "cursor_text_color": "color", 113 "cursor_type": "int", 114 "disable_printing": "bool", 115 "disable_smcup_rmcup": "bool", 116 "disable_window_resizing": "bool", 117 "flashing_bell": "bool", 118 "foreground_color": "color", 119 "horizontal_spacing": "float", 120 "idle_code": "int", 121 "idle_period": "float", 122 "link_color": "color", 123 "minimum_contrast": "float", 124 "mouse_reporting": "bool", 125 "mouse_reporting_allow_mouse_wheel": "bool", 126 "name": "str", 127 "non_ascii_anti_aliased": "bool", 128 "non_ascii_ligatures": "bool", 129 "only_the_default_bg_color_uses_transparency": "bool", 130 "left_option_key_sends": "int", 131 "place_prompt_at_first_column": "bool", 132 "prompt_before_closing": "bool", 133 "reduce_flicker": "bool", 134 "right_option_key_sends": "int", 135 "scrollback_in_alternate_screen": "bool", 136 "scrollback_lines": "int", 137 "scrollback_with_status_bar": "bool", 138 "selected_text_color": "color", 139 "selection_color": "color", 140 "send_bell_alert": "bool", 141 "send_code_when_idle": "bool", 142 "send_idle_alert": "bool", 143 "send_new_output_alert": "bool", 144 "send_session_ended_alert": "bool", 145 "send_terminal_generated_alerts": "bool", 146 "session_close_undo_timeout": "float", 147 "show_mark_indicators": "bool", 148 "silence_bell": "bool", 149 "smart_cursor_color": "color", 150 "smart_cursor_color": "color", 151 "sync_title": "str", 152 "tab_color": "color", 153 "thin_strokes": "int", 154 "transparency": "float", 155 "underline_color": "color", 156 "unicode_normalization": "int", 157 "unicode_version": "int", 158 "unlimited_scrollback": "bool", 159 "use_bold_font": "bool", 160 "use_bright_bold": "bool", 161 "use_cursor_guide": "bool", 162 "use_italic_font": "bool", 163 "use_non_ascii_font": "bool", 164 "use_tab_color": "bool", 165 "use_underline_color": "bool", 166 "vertical_spacing": "float", 167 "visual_bell": "bool", 168 "triggers": "dict", 169 "smart_selection_rules": "list", 170 "semantic_history": "dict", 171 "automatic_profile_switching_rules": "list", 172 "advanced_working_directory_window_setting": "string", 173 "advanced_working_directory_window_directory": "string", 174 "advanced_working_directory_tab_setting": "string", 175 "advanced_working_directory_tab_directory": "string", 176 "advanced_working_directory_pane_setting": "string", 177 "advanced_working_directory_pane_directory": "string", 178 "normal_font": "string", 179 "non_ascii_font": "string", 180 "background_image_location": "string", 181 "key_mappings": "dict", 182 "touchbar_mappings": "dict" } 183 return map 184 185 def profile_properties(): 186 return list(profile_property_type_map().keys()) 187 188 def profile_property_type(key): 189 return profile_property_type_map()[key] 190 191 async def get_profile_property(connection, args): 192 a = await iterm2.async_get_app(connection) 193 s = a.get_session_by_id(args.session) 194 profile = await s.async_get_profile() 195 if args.keys is not None: 196 keys = args.keys.split(",") 197 else: 198 keys = profile_properties() 199 for prop in keys: 200 fname = prop 201 value = getattr(profile, fname) 202 print("{}: {}".format(prop, value)) 203 204 def encode_property_value(key, value): 205 type = profile_property_type(key) 206 if type == "bool": 207 assert value == "true" or value == "false" 208 return value == "true" 209 elif type == "str": 210 return value 211 elif type == "float": 212 return float(value) 213 elif type == "int": 214 return int(value) 215 elif type == "dict" or type == "list": 216 class TypeNotSupportedException(Exception): Pass 217 raise TypeNotSupportedException("this property's type is not supported") 218 elif type == "color": 219 # Accepted values look like: "(0,0,0,255 sRGB)" 220 regex = r"\(([0-9]+), *([0-9]+), *([0-9]+), *([0-9]+) *([A-Za-z]+)\)" 221 match = re.search(regex, value) 222 assert match is not None 223 return iterm2.Color( 224 float(match.group(1)), 225 float(match.group(2)), 226 float(match.group(3)), 227 float(match.group(4)), 228 iterm2.ColorSpace(match.group(5))) 229 230 async def set_profile_property(connection, args): 231 a = await iterm2.async_get_app(connection) 232 s = a.get_session_by_id(args.session) 233 234 encoded_value = encode_property_value(args.key, args.value) 235 profile = await s.async_get_profile() 236 fname = "async_set_" + args.key 237 f = getattr(profile, fname) 238 await f(encoded_value) 239 240 async def read(connection, args): 241 a = await iterm2.async_get_app(connection) 242 s = a.get_session_by_id(args.session) 243 if args.mode == "char": 244 async with iterm2.KeystrokeMonitor(connection) as mon: 245 keystroke = await mon.async_get() 246 print(keystroke) 247 elif args.mode == "line": 248 async with s.get_keystroke_reader() as reader: 249 eol = False 250 line = "" 251 while not eol: 252 k = await reader.get() 253 for e in k: 254 c = e.characters 255 if c == "\r" or c == "\n": 256 eol = True 257 break 258 line += c 259 260 print(line) 261 262 async def get_window_property(connection, args): 263 a = await iterm2.async_get_app(connection) 264 w = a.get_window_by_id(args.id) 265 if w is None: 266 print("bad window ID") 267 else: 268 if args.name == "frame": 269 frame = await w.async_get_frame() 270 print("{},{},{},{}".format(frame.origin.x,frame.origin.y,frame.size.width,frame.size.height)) 271 elif args.name == "fullscreen": 272 print(await w.async_get_fullscreen(connection)) 273 274 async def set_window_property(connection, args): 275 a = await iterm2.async_get_app(connection) 276 w = a.get_window_by_id(args.id) 277 if w is None: 278 print("bad window ID") 279 else: 280 if args.name == "frame": 281 parts = args.value.split(",") 282 frame = iterm2.Frame(iterm2.Point(int(parts[0]), int(parts[1])), iterm2.Size(int(parts[2]), int(parts[3]))) 283 await w.async_set_frame(frame) 284 elif args.name == "fullscreen": 285 await w.async_set_fullscreen(args.value == "true") 286 287 async def inject(connection, args): 288 a = await iterm2.async_get_app(connection) 289 s = a.get_session_by_id(args.session) 290 if s is None: 291 print("bad session ID") 292 else: 293 await s.async_inject(args.data.encode()) 294 295 async def activate(connection, args): 296 a = await iterm2.async_get_app(connection) 297 if args.mode == "session": 298 s = a.get_session_by_id(args.id) 299 if s is None: 300 print("bad session ID") 301 else: 302 await s.async_activate() 303 elif args.mode == "tab": 304 t = a.get_tab_by_id(args.id) 305 if t is None: 306 print("bad tab ID") 307 else: 308 await t.async_select() 309 elif args.mode == "window": 310 w = a.get_window_by_id(args.id) 311 if w is None: 312 print("bad window ID") 313 else: 314 await w.async_activate() 315 316 async def activate_app(connection, args): 317 a = await iterm2.async_get_app(connection) 318 await a.async_activate(raise_all_windows=args.raise_all_windows, ignoring_other_apps=args.ignoring_other_apps) 319 320 async def set_variable(connection, args): 321 a = await iterm2.async_get_app(connection) 322 if args.session: 323 s = a.get_session_by_id(args.session) 324 if s is None: 325 print("bad session ID") 326 return 327 await s.async_set_variable(args.name, args.value) 328 elif args.tab: 329 t = a.get_tab_by_id(args.tab) 330 if t is None: 331 print("bad tab ID") 332 return 333 await t.async_set_variable(args.name, args.value) 334 else: 335 await a.async_set_variable(args.name, args.value) 336 337 async def get_variable(connection, args): 338 a = await iterm2.async_get_app(connection) 339 if args.session: 340 s = a.get_session_by_id(args.session) 341 if s is None: 342 print("bad session ID") 343 return 344 value = await s.async_get_variable(args.name) 345 print(value) 346 elif args.tab: 347 t = a.get_tab_by_id(args.tab) 348 if t is None: 349 print("bad tab ID") 350 return 351 value = await t.async_get_variable(args.name) 352 print(value) 353 else: 354 value = await a.async_get_variable(args.name) 355 print(value) 356 357 async def list_variables(connection, args): 358 a = await iterm2.async_get_app(connection) 359 if args.session: 360 s = a.get_session_by_id(args.session) 361 if s is None: 362 print("bad session ID") 363 return 364 value = await s.async_get_variable("*") 365 for name in value: 366 print(name) 367 elif args.tab: 368 t = a.get_tab_by_id(args.tab) 369 if t is None: 370 print("bad tab ID") 371 return 372 value = await t.async_get_variable("*") 373 for name in value: 374 print(name) 375 else: 376 value = await a.async_get_variable("*") 377 for name in value: 378 print(name) 379 380 async def saved_arrangement(connection, args): 381 if args.window is not None: 382 a = await iterm2.async_get_app(connection) 383 w = a.get_window_by_id(args.window) 384 if w is None: 385 print("bad window ID") 386 return 387 if args.action == "save": 388 await w.async_save_window_as_arrangement(args.name) 389 elif args.action == "restore": 390 await w.async_restore_window_arrangement(args.name) 391 else: 392 a = await iterm2.async_get_app(connection) 393 if args.action == "save": 394 await a.async_save_window_arrangement(args.name) 395 elif args.action == "restore": 396 await a.async_restore_window_arrangement(args.name) 397 398 async def show_focus(connection, args): 399 a = await iterm2.async_get_app(connection) 400 if a.app_active: 401 print("App is active") 402 w = a.current_terminal_window 403 print("Key window: {}".format(w.window_id)) 404 print("") 405 for w in a.terminal_windows: 406 t = a.get_tab_by_id(w.selected_tab_id) 407 print("Selected tab in {}: {}".format(w.window_id, t.tab_id)) 408 s = a.get_session_by_id(t.active_session_id) 409 print(" Active session is: {}".format(s.pretty_str())) 410 411 async def list_profiles(connection, args): 412 guids = args.guids.split(",") if args.guids is not None else None 413 properties = args.properties.split(",") if args.properties is not None else None 414 profiles = await iterm2.PartialProfile.async_query(connection, guids=guids, properties=properties) 415 for profile in profiles: 416 keys = list(profile.all_properties.keys()) 417 keys.sort() 418 for k in keys: 419 v = profile.all_properties[k] 420 print("{}: {}".format(k, v)) 421 print("") 422 423 async def set_grid_size(connection, args): 424 a = await iterm2.async_get_app(connection) 425 s = a.get_session_by_id(args.session) 426 await s.async_set_grid_size(iterm2.Size(args.width, args.height)) 427 428 async def list_tmux_connections(connection, args): 429 connections = await iterm2.async_get_tmux_connections(connection) 430 for connection in connections: 431 print("Connection ID: {}\nOwning session: {}".format(connection.connection_id, connection.owning_session)) 432 433 async def send_tmux_command(connection, args): 434 connections = await iterm2.async_get_tmux_connections(connection) 435 ids = [] 436 for connection in connections: 437 if connection.connection_id == args.connection_id: 438 print(await connection.async_send_command(args.command)) 439 return; 440 ids.append(connection.connection_id) 441 print("No connection with id {} found. Have: {}".format(args.connection_id, ", ".join(ids))) 442 443 async def set_tmux_window_visible(connection, args): 444 connections = await iterm2.async_get_tmux_connections(connection) 445 ids = [] 446 for connection in connections: 447 if connection.connection_id == args.connection_id: 448 await connection.async_set_tmux_window_visible(args.window_id, args.visible) 449 return; 450 ids.append(connection.connection_id) 451 print("No connection with id {} found. Have: {}".format(args.connection_id, ", ".join(ids))) 452 453 async def sort_tabs(connection, args): 454 app = await iterm2.async_get_app(connection) 455 for w in app.terminal_windows: 456 tabs = w.tabs 457 for t in tabs: 458 t.tab_name = await t.async_get_variable("currentSession.session.name") 459 def tab_name(t): 460 return t.tab_name 461 sorted_tabs = sorted(tabs, key=tab_name) 462 await w.async_set_tabs(sorted_tabs) 463 464 async def list_color_presets(connection, args): 465 presets = await iterm2.ColorPreset.async_get_list(connection) 466 for preset in presets: 467 print(preset) 468 469 async def set_color_preset(connection, args): 470 preset = await iterm2.ColorPreset.async_get(connection, args.preset) 471 profiles = await iterm2.PartialProfile.async_query(connection, properties=['Guid', 'Name']) 472 for partial in profiles: 473 if partial.name == args.profile: 474 profile = await partial.async_get_full_profile() 475 await profile.async_set_color_preset(preset) 476 477 async def monitor_variable(connection, args): 478 if args.session: 479 scope = iterm2.VariableScopes.SESSION 480 identifier = args.session 481 elif args.tab: 482 scope = iterm2.VariableScopes.TAB 483 identifier = args.tab 484 elif args.window: 485 scope = iterm2.VariableScopes.WINDOW 486 identifier = args.window 487 elif args.app: 488 scope = iterm2.VariableScopes.APP 489 identifier = '' 490 else: 491 assert False 492 async with iterm2.VariableMonitor(connection, scope, args.name, identifier) as monitor: 493 value = await monitor.async_get() 494 print(f"New value: {value}") 495 496 async def monitor_focus(connection, args): 497 async with iterm2.FocusMonitor(connection) as monitor: 498 update = await monitor.async_get_next_update() 499 print("Update: {}".format(update)) 500 501 async def set_cursor_color(connection, args): 502 a = await iterm2.async_get_app(connection) 503 s = a.get_session_by_id(args.session) 504 partial = iterm2.LocalWriteOnlyProfile() 505 r, g, b = list(map(int, args.color.split(","))) 506 c = iterm2.Color(r, g, b) 507 partial.set_cursor_color(c) 508 await s.async_set_profile_properties(partial) 509 510 async def monitor_screen(connection, args): 511 a = await iterm2.async_get_app(connection) 512 s = a.get_session_by_id(args.session) 513 async with s.get_screen_streamer() as streamer: 514 done = False 515 while not done: 516 contents = await streamer.async_get() 517 for i in range(contents.number_of_lines): 518 line = contents.line(i) 519 if args.query in line.string: 520 return 521 522 async def show_selection(connection, args): 523 a = await iterm2.async_get_app(connection) 524 s = a.get_session_by_id(args.session) 525 selection = await s.async_get_selection() 526 for sub in selection.subSelections: 527 print("Sub selection: {}".format(await sub.async_get_string(connection, s.session_id))) 528 print("Text: {}".format(await selection.async_get_string(connection, s.session_id, s.grid_size.width))) 529 530 def make_parser(): 531 parser = argparse.ArgumentParser(description='iTerm2 CLI') 532 subparsers = parser.add_subparsers(help='Commands') 533 534 list_sessions_parser = subparsers.add_parser("list-sessions", help="List sessions") 535 list_sessions_parser.set_defaults(func=list_sessions) 536 537 show_hierarchy_parser = subparsers.add_parser("show-hierarchy", help="Show all windows, tabs, and sessions") 538 show_hierarchy_parser.set_defaults(func=show_hierarchy) 539 540 send_text_parser = subparsers.add_parser("send-text", help="Send text as though the user had typed it") 541 send_text_parser.add_argument('session', type=str, help='Session ID') 542 send_text_parser.add_argument("text", type=str, help='Text to send') 543 send_text_parser.set_defaults(func=send_text) 544 545 create_tab_parser = subparsers.add_parser("create-tab", help="Create a new tab or window") 546 create_tab_parser.add_argument('--profile', type=str, nargs='?', help='Profile name') 547 create_tab_parser.add_argument('--window', type=str, nargs='?', help='Window ID') 548 create_tab_parser.add_argument('--index', type=int, nargs='?', help='Desired tab index') 549 create_tab_parser.add_argument('--command', type=str, nargs='?', help='Command') 550 create_tab_parser.set_defaults(func=create_tab) 551 552 split_pane_parser = subparsers.add_parser("split-pane", help="Split a pane into two") 553 split_pane_parser.add_argument('session', type=str, help='Session ID') 554 split_pane_parser.add_argument('--vertical', action='store_true', help='Split vertically?', default=False) 555 split_pane_parser.add_argument('--before', action='store_true', help='Spilt left or above target', default=False) 556 split_pane_parser.add_argument('--profile', type=str, nargs='?', help='Profile name') 557 split_pane_parser.set_defaults(func=split_pane) 558 559 get_buffer_parser = subparsers.add_parser("get-buffer", help="Get screen contents") 560 get_buffer_parser.add_argument("session", type=str, help="Session ID") 561 get_buffer_parser.set_defaults(func=get_buffer) 562 563 get_prompt_parser = subparsers.add_parser("get-prompt", help="Get info about prompt, if available. Gives either the current prompt or the last prompt if a command is being run. Requires shell integration for prompt detection.") 564 get_prompt_parser.add_argument("session", type=str, help="Session ID") 565 get_prompt_parser.set_defaults(func=get_prompt) 566 567 get_profile_property_parser = subparsers.add_parser("get-profile-property", help="Get a session's profile settings") 568 get_profile_property_parser.add_argument("session", type=str, help="Session ID") 569 get_profile_property_parser.add_argument("keys", type=str, nargs='?', help="Comma separated keys. Omit to get all. Valid keys are: " + ", ".join(profile_properties())) 570 get_profile_property_parser.set_defaults(func=get_profile_property) 571 572 set_profile_parser = subparsers.add_parser("set-profile-property", help="Set a session's profile setting") 573 set_profile_parser.add_argument("session", type=str, help="Session ID") 574 set_profile_parser.add_argument("key", type=str, help="Key to set. Valid keys are: " + ", ".join(profile_properties())) 575 set_profile_parser.add_argument("value", type=str, help="New value.") 576 set_profile_parser.set_defaults(func=set_profile_property) 577 578 read_parser = subparsers.add_parser("read", help="Wait for a input.") 579 read_parser.add_argument("session", type=str, help="Session ID") 580 read_parser.add_argument("mode", type=str, help="What to read", choices=[ "char", "line" ]) 581 read_parser.set_defaults(func=read) 582 583 get_window_property_parser = subparsers.add_parser("get-window-property", help="Get a property of a window") 584 get_window_property_parser.add_argument("id", type=str, help="Window ID") 585 get_window_property_parser.add_argument("name", type=str, help="Property name", choices=["frame", "fullscreen"]) 586 get_window_property_parser.set_defaults(func=get_window_property) 587 588 set_window_property_parser = subparsers.add_parser("set-window-property", help="Set a property of a window") 589 set_window_property_parser.add_argument("id", type=str, help="Window ID") 590 set_window_property_parser.add_argument("name", type=str, help="Property name", choices=["frame", "fullscreen"]) 591 set_window_property_parser.add_argument("value", type=str, help="New value. For frame: x,y,width,height; for fullscreen: true or false") 592 set_window_property_parser.set_defaults(func=set_window_property) 593 594 inject_parser = subparsers.add_parser("inject", help="Inject a string as though it were program output") 595 inject_parser.add_argument("session", type=str, help="Session ID") 596 inject_parser.add_argument("data", type=str, help="Data to inject") 597 inject_parser.set_defaults(func=inject) 598 599 activate_parser = subparsers.add_parser("activate", help="Activate a session, tab, or window.") 600 activate_parser.add_argument("mode", type=str, help="What kind of object to activate", choices=["session", "tab", "window"]) 601 activate_parser.add_argument("id", type=str, help="ID of object to activate") 602 activate_parser.set_defaults(func=activate) 603 604 activate_app_parser = subparsers.add_parser("activate-app", help="Activate the app") 605 activate_app_parser.add_argument('--raise_all_windows', action='store_true', help='Raise all windows?', default=False) 606 activate_app_parser.add_argument('--ignoring_other_apps', action='store_true', help='Activate ignoring other apps (may steal focus)', default=False) 607 activate_app_parser.set_defaults(func=activate_app) 608 609 set_variable_parser = subparsers.add_parser("set-variable", help="Set a user-defined variable in a session. See Badges documentation for details.") 610 set_variable_parser.add_argument("--session", type=str, nargs='?', help="Session ID") 611 set_variable_parser.add_argument("--tab", type=str, nargs='?', help="Tab ID") 612 set_variable_parser.add_argument("name", type=str, help="Variable name. Starts with \"user.\"") 613 set_variable_parser.add_argument("value", type=str, help="New value") 614 set_variable_parser.set_defaults(func=set_variable) 615 616 get_variable_parser = subparsers.add_parser("get-variable", help="Get a variable in a session. See Badges documentation for details.") 617 get_variable_parser.add_argument("--session", type=str, nargs='?', help="Session ID") 618 get_variable_parser.add_argument("--tab", type=str, nargs='?', help="Tab ID") 619 get_variable_parser.add_argument("name", type=str, help="Variable name. Starts with \"user.\"") 620 get_variable_parser.set_defaults(func=get_variable) 621 622 list_variables_parser = subparsers.add_parser("list-variables", help="Lists variable names available in a session.") 623 list_variables_parser.add_argument("--session", type=str, nargs='?', help="Session ID") 624 list_variables_parser.add_argument("--tab", type=str, nargs='?', help="Tab ID") 625 list_variables_parser.set_defaults(func=list_variables) 626 627 saved_arrangement_parser = subparsers.add_parser("saved-arrangement", help="Saves and restores window arrangements") 628 saved_arrangement_parser.add_argument("action", type=str, help="Action to perform", choices=["save", "restore"]) 629 saved_arrangement_parser.add_argument("name", type=str, help="Arrangement name") 630 saved_arrangement_parser.add_argument('--window', type=str, nargs='?', help='Window ID to save/restore to') 631 saved_arrangement_parser.set_defaults(func=saved_arrangement) 632 633 show_focus_parser = subparsers.add_parser("show-focus", help="Show active windows, tabs, and panes") 634 show_focus_parser.set_defaults(func=show_focus) 635 636 list_profiles_parser = subparsers.add_parser("list-profiles", help="List profiles") 637 list_profiles_parser.add_argument("--guids", type=str, nargs='?', help="Comma-delimited list of profiles to list. Omit to get all of them.") 638 list_profiles_parser.add_argument("--properties", type=str, nargs='?', help="Comma-delimited list of properties to request. Omit to get all of them.") 639 list_profiles_parser.set_defaults(func=list_profiles) 640 641 set_grid_size_parser = subparsers.add_parser("set-grid-size", help="Set size of session") 642 set_grid_size_parser.add_argument("session", type=str, help="Session ID") 643 set_grid_size_parser.add_argument("width", type=int, help="Width in columns") 644 set_grid_size_parser.add_argument("height", type=int, help="Height in rows") 645 set_grid_size_parser.set_defaults(func=set_grid_size) 646 647 list_tmux_connections_parser = subparsers.add_parser("list-tmux-connections", help="List tmux integration connections") 648 list_tmux_connections_parser.set_defaults(func=list_tmux_connections) 649 650 send_tmux_command_parser = subparsers.add_parser("send-tmux-command", help="Send a tmux command to a tmux integration connection") 651 send_tmux_command_parser.add_argument("connection_id", type=str, help="tmux connection ID") 652 send_tmux_command_parser.add_argument("command", type=str, help="Command to send") 653 send_tmux_command_parser.set_defaults(func=send_tmux_command) 654 655 set_tmux_window_visible_parser = subparsers.add_parser("set-tmux-window-visible", help="Show or hide a tmux integration window (represented as a tab in iTerm2)") 656 set_tmux_window_visible_parser.add_argument("connection_id", type=str, help="tmux connection ID") 657 set_tmux_window_visible_parser.add_argument("window_id", type=str, help="tmux window ID (number)") 658 set_tmux_window_visible_parser.add_argument('--visible', dest='visible', action='store_true') 659 set_tmux_window_visible_parser.add_argument('--no-visible', dest='visible', action='store_false') 660 set_tmux_window_visible_parser.set_defaults(visible=True) 661 set_tmux_window_visible_parser.set_defaults(func=set_tmux_window_visible) 662 663 sort_tabs_parser = subparsers.add_parser("sort-tabs", help="Sort tabs alphabetically by name") 664 sort_tabs_parser.set_defaults(func=sort_tabs) 665 666 list_color_presets_parser = subparsers.add_parser("list-color-presets", help="Lists names of color presets") 667 list_color_presets_parser.set_defaults(func=list_color_presets) 668 669 set_color_preset_parser = subparsers.add_parser("set-color-preset", help="Lists names of color presets") 670 set_color_preset_parser.add_argument("profile", type=str, help="Profile name") 671 set_color_preset_parser.add_argument("preset", type=str, help="Color preset name") 672 set_color_preset_parser.set_defaults(func=set_color_preset) 673 674 monitor_variable_parser = subparsers.add_parser("monitor-variable", help="Monitor changes to a variable") 675 monitor_variable_parser.add_argument("name", type=str, help="variable name") 676 monitor_variable_parser.add_argument('--session', type=str, nargs='?', help='Session ID for the variable scope') 677 monitor_variable_parser.add_argument('--tab', type=str, nargs='?', help='Tab ID for the variable scope') 678 monitor_variable_parser.add_argument('--window', type=str, nargs='?', help='Window ID for the variable scope') 679 monitor_variable_parser.add_argument('--app', action='store_true', help='App scope', default=False) 680 monitor_variable_parser.set_defaults(func=monitor_variable) 681 682 monitor_focus_parser = subparsers.add_parser("monitor-focus", help="Monitor changes to focus") 683 monitor_focus_parser.set_defaults(func=monitor_focus) 684 685 set_cursor_color_parser = subparsers.add_parser("set-cursor-color", help="Set cursor color") 686 set_cursor_color_parser.add_argument("session", type=str, help="Session ID") 687 set_cursor_color_parser.add_argument("color", type=str, help="Color as red,green,blue where each value is in 0-255") 688 set_cursor_color_parser.set_defaults(func=set_cursor_color) 689 690 monitor_screen_parser = subparsers.add_parser("monitor-screen", help="Monitor screen contents") 691 monitor_screen_parser.add_argument("session", type=str, help="Session ID") 692 monitor_screen_parser.add_argument("query", type=str, help="Stop when this text is seen") 693 monitor_screen_parser.set_defaults(func=monitor_screen) 694 695 show_selection_parser = subparsers.add_parser("show-selection", help="Shows the selected text in a session") 696 show_selection_parser.add_argument("session", type=str, help="Session ID") 697 show_selection_parser.set_defaults(func=show_selection) 698 699 return parser 700 701 def main(argv): 702 logging.basicConfig() 703 704 parser = make_parser() 705 args = parser.parse_args(argv[1:]) 706 if "func" not in args: 707 print(parser.format_help()) 708 raise argparse.ArgumentTypeError('Missing command') 709 710 async def wrapper(connection): 711 try: 712 await args.func(connection, args) 713 except Exception as e: 714 print(traceback.format_exc()) 715 716 iterm2.run_until_complete(wrapper) 717 718 if __name__ == "__main__": 719 try: 720 main(sys.argv) 721 except Exception as e: 722 print(traceback.format_exc()) 723 sys.exit(1)