async def main(connection): component = iterm2.StatusBarComponent( short_description='GitHub stars', detailed_description='How many stars a GitHub repository has', exemplar='some-user/project ★ 103', update_cadence=300, identifier='engineering.dane.iterm-components.github-stars', knobs=[ iterm2.StringKnob('Repository', 'some-user/project', 'some-user/project', REPO_KNOB_NAME), iterm2.StringKnob('Personal access token', 'token value (optional, for rate limiting or private repos)', '', TOKEN_KNOB_NAME) ], ) @iterm2.StatusBarRPC async def github_stars_coroutine(knobs): github_repo = knobs[REPO_KNOB_NAME] token = knobs[TOKEN_KNOB_NAME] info_url = f'https://api.github.com/repos/{github_repo}' try: request = urllib.request.Request( info_url, headers={'Authorization': f'token {token}'} if token else {}, ) stars = json.loads( urllib.request.urlopen(request).read().decode() )['stargazers_count'] stars = human_number(stars) except: raise else: return f'{github_repo} ★ {stars}' await component.async_register(connection, github_stars_coroutine)
async def main(connection): component = iterm2.StatusBarComponent( short_description='Execute a user defined command', detailed_description='A component that displays the output of an arbitrary command with an optional prefix', exemplar='> hello world', update_cadence=7, identifier='engineering.dane.iterm-components.generic-command', knobs=[ iterm2.StringKnob('Script', 'echo "hello world"', '', SCRIPT), iterm2.StringKnob('Prefix', '>', '', PREFIX) ], ) @iterm2.StatusBarRPC async def generic_command_coroutine(knobs): proc = await asyncio.create_subprocess_shell( knobs[SCRIPT], stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE, ) stdout, stderr = await proc.communicate() prefix = knobs[PREFIX] prefix = f'{prefix} ' if prefix else '' return f'{prefix}{stdout.decode().strip()}' if not stderr else 'Command failed!' await component.async_register(connection, generic_command_coroutine)
async def main(connection): app = await iterm2.async_get_app(connection) # Start fetching the URL asyncio.create_task(updater(app, type='current')) asyncio.create_task(updater(app, type='forecast')) location_knob = "weather_location" update_interval_knob = "weather_update_interval" knobs = [ iterm2.StringKnob("Location", "Hangzhou", "Hangzhou", location_knob), iterm2.StringKnob("Update Interval", "60", "60", update_interval_knob) ] # icon1x = iterm2.StatusBarComponent.Icon(1, ICON1X) # icon2x = iterm2.StatusBarComponent.Icon(2, ICON2X) # Register the status bar component. component = iterm2.StatusBarComponent( short_description="Weather", detailed_description="Shows your local weather", knobs=knobs, exemplar="☁️Weather", update_cadence=None, identifier="catj.moe.weather") @iterm2.StatusBarRPC async def weather(knobs, value=iterm2.Reference("iterm2.user." + CURRENT_VARIABLE + "?")): """This function returns the value to show in a status bar.""" global city global update_interval if location_knob in knobs and knobs[location_knob]: city = knobs[location_knob] if update_interval_knob in knobs and knobs[update_interval_knob]: update_interval = int(knobs[update_interval_knob]) if value: return value return "Loading…" @iterm2.RPC async def onclick(session_id): session = app.get_session_by_id(session_id) forecast_weather = "Loading" try: forecast_weather = await format_weather(app) except: forecast_weather = "Loading" if forecast_weather is not None: await component.async_open_popover(session_id, forecast_weather, iterm2.util.Size(480, 520)) # Register the component. await component.async_register(connection, weather, onclick=onclick)
async def main(connection): api_key = "atlas_api_key" knobs = [iterm2.StringKnob("API key", "API KEY", "", api_key)] component = iterm2.StatusBarComponent( short_description="RIPE Atlas Credits", detailed_description="Shows credits balance at atlas.ripe.net", knobs=knobs, exemplar="0.0 / 34,000.0 / 4,000,000.0", update_cadence=300, identifier="com.iterm2.example.status-bar") @iterm2.StatusBarRPC async def coro(knobs): URL = 'https://atlas.ripe.net/api/v2/credits/' PARAMS = {'key': knobs[api_key]} try: r = requests.get(url=URL, params=PARAMS) data = r.json() daily = data['estimated_daily_income'] total = data['current_balance'] expenditure = data['estimated_daily_expenditure'] except: raise else: return f'{float(expenditure):,.1f} / {float(daily):,.1f} / {float(total):,.1f}' await component.async_register(connection, coro)
async def main(connection): fmt = 'fmt' default_fmt = '%m/%d %a %H:%M:%S' knobs = [ iterm2.StringKnob(name='format', placeholder=default_fmt, default_value=default_fmt, key=fmt) ] component = iterm2.StatusBarComponent( short_description='Clock', detailed_description='A customized clock.', knobs=knobs, exemplar=' 08/03 Sat 01:56:48', update_cadence=1, identifier='peinan.clock') @iterm2.StatusBarRPC async def clock(knobs): n = datetime.now() clock_char = '' if fmt in knobs and knobs[fmt]: clock_face = f'{clock_char} {n.strftime(knobs[fmt])}' else: clock_face = f'{clock_char} {n.strftime(default_fmt)}' return clock_face await component.async_register(connection, clock)
async def main(connection): knob_icons = KnobOption('icons', '') knob_free = KnobOption('free', True) knob_usedtotal = KnobOption('usedtotal', True) knob_usedpercent = KnobOption('usedpercent', True) knobs = [ iterm2.StringKnob(name='Icons', default_value=knob_icons.v, placeholder=knob_icons.v, key=knob_icons.name), iterm2.CheckboxKnob(name='Show Free Space', default_value=knob_free.v, key=knob_free.name), iterm2.CheckboxKnob(name='Show Used/Total Space', default_value=knob_usedtotal.v, key=knob_usedtotal.name), iterm2.CheckboxKnob(name='Show Used Space (%)', default_value=knob_usedpercent.v, key=knob_usedpercent.name), ] component = iterm2.StatusBarComponent( short_description='Disk Usage', detailed_description='Display the usage of disk.', knobs=knobs, exemplar=' 44.1 GB 179.7/233.5 GB (81.0%)', update_cadence=2, identifier='peinan.diskusage') def is_true_knob(knobs, knob_option: KnobOption): return knob_option.name in knobs and knobs[knob_option.name] @iterm2.StatusBarRPC async def diskusage(knobs): true_icons = is_true_knob(knobs, knob_icons) true_free = is_true_knob(knobs, knob_free) true_usedtotal = is_true_knob(knobs, knob_usedtotal) true_usedpercent = is_true_knob(knobs, knob_usedpercent) char_header = knobs[knob_icons.name][0] if true_icons else '' char_usedtotal = f' {knobs[knob_icons.name][-1]}' if true_icons and true_free and true_usedtotal else '' disk = shutil.disk_usage('/') unit = sizeof_fmt(disk.total)[1] v_free = f' {" ".join(sizeof_fmt(disk.free))}' if true_free else '' v_usedtotal = f' {sizeof_fmt(disk.used)[0]}/{sizeof_fmt(disk.total)[0]} {unit}' if true_usedtotal else '' v_usedp = f' ({100 * disk.used / disk.total:.1f}%)' if (true_free or true_usedtotal) and true_usedpercent\ else f' {100 * disk.used / disk.total:.1f}%' if true_usedpercent else '' usage = f'{char_header}{v_free}{char_usedtotal}{v_usedtotal}{v_usedp}' return usage await component.async_register(connection, diskusage)
async def main(connection, update_cadence=5): # configure iTerm2 status bar interface knobs = [iterm2.StringKnob("CPU Temperature", "N/A", "", "CPU")] component = iterm2.StatusBarComponent( short_description="CPU temperature", detailed_description= "Reads CPU temperature at a specified refresh rate", knobs=knobs, exemplar="48.8°C", update_cadence=update_cadence, identifier="com.github.sheatsley.temperature", ) @iterm2.StatusBarRPC async def temperature_component(knobs): return check_output("/usr/local/bin/osx-cpu-temp", encoding="utf-8").strip() await component.async_register(connection, temperature_component)
async def main(connection): component = iterm2.StatusBarComponent( short_description='Environment variable', detailed_description= 'Show the current value of an environment variable', exemplar='SOME_ENV_VAR=foo', update_cadence=3, identifier='engineering.dane.iterm-components.environment-variable', knobs=[ iterm2.StringKnob('Variable name', 'SOME_ENV_VAR', 'SOME_ENV_VAR', ENV_VAR_KNOB_NAME), iterm2.CheckboxKnob('Show variable name', True, SHOW_NAME_KNOB_NAME) ], ) @iterm2.StatusBarRPC async def env_var_coroutine(knobs): env_var_name = knobs[ENV_VAR_KNOB_NAME] show_name = knobs[SHOW_NAME_KNOB_NAME] prefix = f'{env_var_name}=' if show_name else '' return f'{prefix}{os.getenv(env_var_name, "")}' await component.async_register(connection, env_var_coroutine)
async def main(connection): app = await iterm2.async_get_app(connection) icon = iterm2.StatusBarComponent.Icon(1, ICON) icon2x = iterm2.StatusBarComponent.Icon(2, ICON2X) # Register the status bar component # The username and bearer token are configurable values component = iterm2.StatusBarComponent( short_description='Twitter followers', detailed_description='Shows count of Twitter followers', exemplar='3401', update_cadence=600, identifier='andypiper.iterm-twitter-info.user-count', knobs=[ iterm2.StringKnob('Twitter user', 'username', 'twitterdev', USER_KNOB_NAME), iterm2.StringKnob('Bearer token', 'bearer token value', 'xxxxxx', TOKEN_KNOB_NAME) ], icons=[icon, icon2x]) @iterm2.StatusBarRPC async def twitter_user_count(knobs): twitter_user = knobs[USER_KNOB_NAME] token = knobs[TOKEN_KNOB_NAME] # we need to put the username into a session variable to pass to the click handler try: session = app.current_terminal_window.current_tab.current_session except Exception: return await session.async_set_variable("user.twitter_user", twitter_user) # this is the API endpoint to get user data, with metrics requested user_url = f'https://api.twitter.com/2/users/by/username/{twitter_user}?user.fields=public_metrics' try: request = urllib.request.Request( user_url, headers={'Authorization': f'Bearer {token}'} if token else {}, ) followers = json.loads( urllib.request.urlopen(request).read().decode() )['data']['public_metrics']['followers_count'] return f'{followers}' except Exception: raise else: return f'{followers}' @iterm2.RPC async def onclick(session_id): try: session = app.current_terminal_window.current_tab.current_session except Exception: return # grab the username from the session user variable twitter_user = await session.async_get_variable("user.twitter_user") # open a browser window to the Twitter user profile proc = await asyncio.create_subprocess_shell( f'open https://twitter.com/{twitter_user}', stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE, ) stdout, stderr = await proc.communicate() await component.async_register(connection, twitter_user_count, onclick=onclick)
async def main(connection): knobs = [ iterm2.StringKnob("OpenWeatherMap API key", "API_KEY", "", API_KEY), iterm2.StringKnob("Location name", "LOCATION_NAME", "", LOCATION_NAME), iterm2.CheckboxKnob("Add Humidity", False, HUMIDITY), iterm2.CheckboxKnob("Add Pressure", False, PRESSURE), iterm2.CheckboxKnob("Add Max Temperatur", False, MAX_TEMPERTUR), iterm2.CheckboxKnob("Add Min Temperatur", False, MIN_TEMPERTUR) ] component = iterm2.StatusBarComponent( short_description="Weather", detailed_description="This is weather status bar", knobs=knobs, exemplar="18℃ 🌙", update_cadence=50, identifier="take.weather") # request api def request_api(api_key, location): url = API_URL.format(location, api_key) response = requests.get(url) forecast_data = json.loads(response.text) if response.status_code == 401: return forecast_data elif response.status_code == 404: return forecast_data return forecast_data # get icon def get_icon(icon_id): if icon_id == "01d": return "☀️" elif icon_id == "01n": return "🌙" elif icon_id == "02d" or icon_id == "02n" or icon_id == "03d" or icon_id == "03n" or icon_id == "04d" or icon_id == "04n": return "☁️" elif icon_id == "09d" or icon_id == "09n": return "🌧" elif icon_id == "10d" or icon_id == "10n": return "☔️" elif icon_id == "11d" or icon_id == "11n": return "⚡️" elif icon_id == "13d" or icon_id == "13n": return "❄️" elif icon_id == "50d" or icon_id == "50n": return "🌫️" # status result def result_status(forecast_data, config): degree = forecast_data["main"]["temp"] icon = get_icon(forecast_data["weather"][0]["icon"]) status = "{0}℃ {1}".format(degree, icon) if config["humidity"]: humidity = forecast_data["main"]["humidity"] status = status + " H:{0}%".format(humidity) if config["pressure"]: pressure = forecast_data["main"]["pressure"] status = status + " P:{0}".format(pressure) if config["max_temp"]: max_temp = forecast_data["main"]["temp_max"] status = status + " HT:{0}".format(max_temp) if config["min_temp"]: min_temp = forecast_data["main"]["temp_min"] status = status + " LT:{0}".format(min_temp) return status # checkbox info def get_checkbox_config(knobs): humidity = knobs[HUMIDITY] pressure = knobs[PRESSURE] max_temp = knobs[MAX_TEMPERTUR] min_temp = knobs[MIN_TEMPERTUR] config = { "humidity": humidity, "pressure": pressure, "max_temp": max_temp, "min_temp": min_temp } return config @iterm2.StatusBarRPC async def weather_component(knobs): # global variable global counter global status global forecast_data global time api_key = knobs[API_KEY] location = knobs[LOCATION_NAME] if not api_key: return "Please set API key" if not location: return "Please set location name" if counter == 0: # first excute config = get_checkbox_config(knobs) forecast_data = request_api(api_key, location) print(type(forecast_data["cod"])) print(forecast_data["cod"]) if forecast_data["cod"] == 401: return "Invalid API key" elif forecast_data["cod"] == "404": return forecast_data["message"] status = result_status(forecast_data, config) time = datetime.datetime.now() counter += 1 else: now_time = datetime.datetime.now() delta = now_time - time config = get_checkbox_config(knobs) status = result_status(forecast_data, config) # api reuest time 10m if int(delta.total_seconds()) > 600: delta = now_time - time config = get_checkbox_config(knobs) forecast_data = request_api(api_key, location) if forecast_data["cod"] == 401: return "Invalid API key" elif forecast_data["cod"] == "404": return forecast_data["message"] status = result_status(forecast_data, config) time = datetime.datetime.now() return status await component.async_register(connection, weather_component)
async def main(connection): knob_city = KnobOption('city', 'Shibuya') knob_use_icon = KnobOption('use_icon', True) knob_use_imperial = KnobOption('use_imperial', False) knob_show_forecast = KnobOption('show_forecast', True) knobs = [ iterm2.StringKnob('City', knob_city.v, knob_city.v, knob_city.name), iterm2.CheckboxKnob('Use icon', knob_use_icon.v, knob_use_icon.name), iterm2.CheckboxKnob('Show forecast', knob_show_forecast.v, knob_show_forecast.name), iterm2.CheckboxKnob('Use imperial units', knob_use_imperial.v, knob_use_imperial.name), ] component = iterm2.StatusBarComponent( short_description='Weather Info', detailed_description= 'A component that will tell you the current weather and the forecast.', knobs=knobs, exemplar=' Clouds 27.1 Clear 30.2', update_cadence=60, identifier='peinan.weather') def have_log(): return LOGFILE_PATH.exists() def is_refresh_time(): return datetime.now().minute % 10 == 0 def is_opt_modify(knobs): opt_set = { k.name for k in [knob_city, knob_use_icon, knob_use_imperial, knob_show_forecast] } if set(knobs.keys()) & opt_set == opt_set: return True return False def read_log(): return json.load(LOGFILE_PATH.open()) def write_log(city: str, use_icon: bool, units: str, show_forecast: bool, weather_info: str): log_data = { 'city': city, 'use_icon': use_icon, 'units': units, 'show_forecast': show_forecast, 'weather_info': weather_info } json.dump(log_data, LOGFILE_PATH.open('w'), ensure_ascii=False) def knob_value(knobs, option: KnobOption, default_value): """returns the option's value if the option is in the knob, otherwise returns False""" return knobs[option.name] if option.name in knobs else default_value @iterm2.StatusBarRPC async def weather_info(knobs): w.CITYNAME = knob_value(knobs, knob_city, 'Shibuya') w.UNITS = 'imperial' if knob_value(knobs, knob_use_imperial, False) else 'metric' use_icon = bool(knob_value(knobs, knob_use_icon, True)) show_forecast = bool(knob_value(knobs, knob_show_forecast, True)) ## for debug # print(f'knobs: {knobs}') # print(f'have log file: {have_log()}, is refresh time: {is_refresh_time()}') if have_log(): log_data = read_log() opt_req = is_opt_modify(knobs) is_same_opt = w.CITYNAME == log_data['city'] and w.UNITS == log_data['units'] and \ use_icon == log_data['use_icon'] and show_forecast == log_data['show_forecast'] # print(f'is knob option request: {opt_req}, is same knob options: {is_same_opt}') if not opt_req or (is_same_opt and not is_refresh_time()): # print(f'[application info] Use stored weather info: ' # f'city={w.CITYNAME}, units={w.UNITS}, use_icon={use_icon}, show_forecast={show_forecast}') return log_data['weather_info'] print(f'[application info] Fetching weather: {knobs}') w.fetch_weather() w.parse_weather() weather_info = w.iterm_format(use_icon=use_icon, show_forecast=show_forecast) write_log(w.CITYNAME, use_icon, w.UNITS, show_forecast, weather_info) return weather_info await component.async_register(connection, weather_info)