# Escape Key Indicator¶

This script defines a custom status bar control that shows an indicator briefly after you press the escape key. This is useful if you are afflicted with a touch bar.

This script demonstrates a custom status bar component, a keyboard monitor, and using user-defined variables to make the keyboard monitor elicit a change in the status bar. It also demonstrates using asyncio tasks to perform an action after a delay, as well as how to cancel asyncio tasks.

After starting this script, navigate to Preferences > Profiles > Session. Turn on Status Bar Enabled and select Configure Status Bar. Drag the Esc Key Indicator component into the bottom section.

This script is a long-running daemon since it must continually update the status bar. As such, it should go in the AutoLaunch folder.

#!/usr/bin/env python3.7

import asyncio
import iterm2

counter = 0

async def main(connection):
app = await iterm2.async_get_app(connection)

component = iterm2.StatusBarComponent(
short_description="Esc Key Indicator",
detailed_description="Shows a visual indicator when the esc key is pressed",
knobs=[],
exemplar="[esc]",
identifier="com.iterm2.escindicator")

async def reset(session):
await asyncio.sleep(2)
await session.async_set_variable("user.showEscIndicator", False)

async def keystroke_handler(keystroke):
"""This function is called every time a key is pressed."""
if keystroke.keycode != iterm2.Keycode.ESCAPE:
return

# There might not be a current session, so there might be an exception
# while trying to get it.
try:
session = app.current_terminal_window.current_tab.current_session
except:
return

# The status bar coro will only be called when the variable changes,
# so the value must be different each time. This only matters if you
# press esc while reset() is still sleeping.
global counter
counter += 1
await session.async_set_variable("user.showEscIndicator", counter)

# The user variable showEscIndicator is used as a communications channel
# between the keyboard monitor and the status bar component coro. Since it
# may not always be defined (e.g., when a new session is created) it must be
# labeled as optional with the trailing ? to prevent an exception.
@iterm2.StatusBarRPC
async def coro(
knobs,
show_indicator=iterm2.Reference("user.showEscIndicator?"),
session_id=iterm2.Reference("id")):
"""This function gets called when showEscIndicator changes in any
session."""
if show_indicator:

return "[ESC]"
else:
return "     "

# Register the status bar component.
await component.async_register(connection, coro)

# Monitor the keyboard
async with iterm2.KeystrokeMonitor(connection) as mon:
while True:
keystroke = await mon.async_get()
await keystroke_handler(keystroke)

iterm2.run_forever(main)


Download