diff --git a/py3status/modules/external_script.py b/py3status/modules/external_script.py index 21a8f385a3..3d2a5ba427 100644 --- a/py3status/modules/external_script.py +++ b/py3status/modules/external_script.py @@ -15,21 +15,68 @@ format: see placeholders below (default '{output}') localize: should script output be localized (if available) (default True) + notifications: specify a nested dict to send a notification if matched + against the keys, see ``Notifications`` section for more information + (default {}) script_path: script you want to show output of (compulsory) (default None) strip_output: shall we strip leading and trailing spaces from output (default False) Format placeholders: - {output} output of script given by "script_path" + {line} number of lines in the output + {output} first line of the output of script given by "script_path" + {output_full} full output of script given by "script_path" -i3status.conf example: +Notifications: + Specify a nested dictionary of notification states and options to use. + Notification states: + 'changed': display a notification only if it is changed + 'click': display a notification of last output on click + 'current': display a current notification regardless + + Notification options: + 'title': notification title + 'msg': notification message + 'level': must be 'info', 'error' or 'warning'. + 'rate_limit': time period in seconds not to be repeated + 'icon': must be an icon path or icon name. + + You can add `format` placeholders in `msg` and `title`. + The `msg` and `title` options will also be formatted. + +Examples: ``` +# add a script external_script { format = "my name is {output}" script_path = "/usr/bin/whoami" } + +# display changed notifications, same output means no notification +external_script { + notifications = {'changed': {'msg': '{output}'}} + script_path = "~/my_script.py" +} + +# display current notifications, no output means no notification +external_script { + notifications = {'current': {'msg': '{output}'}} + script_path = "~/my_script.py" +} + +# display current notification only if output have more than 20 lines +external_script { + notifications = {'current': {'msg': '\?if=line>20 {output}'}} + script_path = "~/my_script.py" +} + +# display a notification of last full output on click +external_script { + notifications = {'click': {'msg': '{output_full}'}} + script_path = "~/my_script.py" +} ``` @author frimdo ztracenastopa@centrum.cz @@ -52,6 +99,7 @@ class Py3status: cache_timeout = 15 format = '{output}' localize = True + notifications = {} script_path = None strip_output = False @@ -59,13 +107,47 @@ def post_config_hook(self): if not self.script_path: raise Exception(STRING_ERROR) + self.button_refresh = 2 + self.notification = {'normal': [], 'click': False} + if self.notifications: + for x in ['changed', 'click', 'current']: + self.notification[x] = self.notifications.get(x, False) + if self.notification[x]: + if x in ['changed', 'current']: + self.notification['normal'].append(x) + self.last_changed = self.py3.storage_get('changed') + + def _get_notification(self, state): + temporary = self.notification[state].copy() + for x in ['title', 'msg']: + if x in temporary: + temporary[x] = self.py3.get_composite_string( + self.py3.safe_format(temporary[x], self.script_data) + ) + return temporary + + def _notify_user(self, state=None): + if state is None: + if self.notification['changed']: + changed = self._get_notification('changed') + if changed != self.last_changed: + self.last_changed = changed + self.py3.storage_set('changed', changed) + self.py3.notify_user(**changed) + if self.notification['current']: + self.py3.notify_user(**self._get_notification('current')) + elif state == 'click': + self.py3.notify_user(**self._get_notification('click')) + def external_script(self): output_lines = None response = {} response['cached_until'] = self.py3.time_in(self.cache_timeout) try: - output = self.py3.command_output(self.script_path, shell=True, localized=self.localize) - output_lines = output.splitlines() + output_full = self.py3.command_output( + self.script_path, shell=True, localized=self.localize + ) + output_lines = output_full.splitlines() if len(output_lines) > 1: output_color = output_lines[1] if re.search(r'^#[0-9a-fA-F]{6}$', output_color): @@ -96,10 +178,28 @@ def external_script(self): else: output = '' + self.script_data = { + 'line': len(output_lines), + 'output': output, + 'output_full': ' '.join(output_full.splitlines()) + } response['full_text'] = self.py3.safe_format( - self.format, {'output': output}) + self.format, self.script_data + ) + + self.script_data['output_full'] = output_full + if self.notification['normal']: + self._notify_user() + return response + def on_click(self, event): + button = event["button"] + if button != self.button_refresh: + if self.notification['click']: + self._notify_user('click') + self.py3.prevent_refresh() + if __name__ == "__main__": """