diff --git a/pywal/__main__.py b/pywal/__main__.py index 91ead11f..5983ed4e 100644 --- a/pywal/__main__.py +++ b/pywal/__main__.py @@ -67,6 +67,9 @@ def get_args(): arg.add_argument("--vte", action="store_true", help="Fix text-artifacts printed in VTE terminals.") + arg.add_argument("--active-only", action="store_true", + help="Only send sequences to active terminals.") + arg.add_argument("-c", action="store_true", help="Delete all cached colorschemes.") @@ -200,7 +203,9 @@ def parse_args(parser): if args.p: theme.save(colors_plain, args.p, args.l) - sequences.send(colors_plain, to_send=not args.s, vte_fix=args.vte) + sequences.send( + colors_plain, to_send=not args.s, + vte_fix=args.vte, only_active=args.active_only) if sys.stdout.isatty(): colors.palette() diff --git a/pywal/sequences.py b/pywal/sequences.py index 8b81323f..7a67aecf 100644 --- a/pywal/sequences.py +++ b/pywal/sequences.py @@ -70,7 +70,8 @@ def create_sequences(colors, vte_fix=False): return "".join(sequences) -def send(colors, cache_dir=CACHE_DIR, to_send=True, vte_fix=False): +def send(colors, cache_dir=CACHE_DIR, to_send=True, + vte_fix=False, only_active=False): """Send colors to all open terminals.""" if OS == "Darwin": tty_pattern = "/dev/ttys00[0-9]*" @@ -82,8 +83,13 @@ def send(colors, cache_dir=CACHE_DIR, to_send=True, vte_fix=False): # Writing to "/dev/pts/[0-9] lets you send data to open terminals. if to_send: + ttys = None + if only_active: + ttys = util.fetch_active_ttys() + for term in glob.glob(tty_pattern): - util.save_file(sequences, term) + util.save_to_tty( + sequences, term, active_ttys=ttys) util.save_file(sequences, os.path.join(cache_dir, "sequences")) logging.info("Set terminal colors.") diff --git a/pywal/settings.py b/pywal/settings.py index cb32c421..e0400878 100644 --- a/pywal/settings.py +++ b/pywal/settings.py @@ -13,7 +13,7 @@ import platform -__version__ = "3.3.1" +__version__ = "3.3.2" __cache_version__ = "1.1.0" diff --git a/pywal/util.py b/pywal/util.py index 1fdae31b..787494b7 100644 --- a/pywal/util.py +++ b/pywal/util.py @@ -134,6 +134,35 @@ def save_file(data, export_file): logging.warning("Couldn't write to %s.", export_file) +def save_to_tty(data, tty_name, active_ttys=None): + """Write data to a tty.""" + if active_ttys: + if os.path.basename(tty_name) not in active_ttys: + logging.info("Not saving to inactive tty %s.", tty_name) + return + save_file(data, tty_name) + + +def fetch_active_ttys(): + """Fetches the active ttys as determined + by the `who` utility. On failure, we return None.""" + try: + out, err = subprocess.Popen( + ["who"], stdout=subprocess.PIPE).communicate() + except FileNotFoundError: + # who is not installed on the machine + return None + + if err: + logging.warning( + "Received stderr output while checking active ttys: %s", + err.decode('utf-8')) + return None + lines = out.decode('utf-8').split("\n") + # The format is `username tty ...` and we just want tty + return [line.split(' ')[1] for line in lines if line] + + def save_file_json(data, export_file): """Write data to a json file.""" create_dir(os.path.dirname(export_file)) diff --git a/tests/test_util.py b/tests/test_util.py index 79b6b960..d9d73619 100755 --- a/tests/test_util.py +++ b/tests/test_util.py @@ -46,6 +46,26 @@ def test_save_file_json(self): result = os.path.isfile(tmp_file) self.assertTrue(result) + def test_save_to_tty_active_tty_saves(self): + """> Save colors to an active tty.""" + tmp_file = "/tmp/test_tty_file_active" + util.save_to_tty("Hello, World!", tmp_file, ["test_tty_file_active"]) + result = os.path.isfile(tmp_file) + self.assertTrue(result) + + def test_save_to_tty_inactive_does_not_save(self): + """> Does not save colors to an inactive tty.""" + tmp_file = "/tmp/test_tty_file_inactive" + util.save_to_tty("Hello, World!", tmp_file, ["test_tty_file_active"]) + result = os.path.isfile(tmp_file) + self.assertFalse(result) + + def test_save_to_tty_inactive_no_ttys_saves(self): + tmp_file = "/tmp/test_tty_file_inactive_save" + util.save_to_tty("Hello, World!", tmp_file, []) + result = os.path.isfile(tmp_file) + self.assertTrue(result) + def test_create_dir(self): """> Create a directory.""" tmp_dir = "/tmp/test_dir"