autoreload.py 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364
  1. #!/usr/bin/env python3
  2. """Usage: ./autoreload.py [MIRAGE_ARGUMENTS]...
  3. Automatically rebuild and restart the application when source files change.
  4. CONFIG+=dev will be passed to qmake, see mirage.pro.
  5. The application will be launched with `-name dev`, which sets the first
  6. part of the WM_CLASS as returned by xprop on Linux.
  7. Any other arguments will be passed to the app, see `mirage --help`.
  8. Use `pip3 install --user -U requirements-dev.txt` before running this."""
  9. import os
  10. import subprocess
  11. import sys
  12. from contextlib import suppress
  13. from pathlib import Path
  14. from shutil import get_terminal_size as term_size
  15. from watchgod import DefaultWatcher, run_process
  16. ROOT = Path(__file__).parent
  17. class Watcher(DefaultWatcher):
  18. def accept_change(self, entry: os.DirEntry) -> bool:
  19. path = Path(entry.path)
  20. for bad in ("src/config", "src/themes"):
  21. if path.is_relative_to(ROOT / bad):
  22. return False
  23. for good in ("src", "submodules"):
  24. if path.is_relative_to(ROOT / good):
  25. return True
  26. return False
  27. def should_watch_dir(self, entry: os.DirEntry) -> bool:
  28. return super().should_watch_dir(entry) and self.accept_change(entry)
  29. def should_watch_file(self, entry: os.DirEntry) -> bool:
  30. return super().should_watch_file(entry) and self.accept_change(entry)
  31. def cmd(*parts) -> subprocess.CompletedProcess:
  32. return subprocess.run(parts, cwd=ROOT, check=True)
  33. def run_app(args=sys.argv[1:]) -> None:
  34. print("\n\x1b[36m", "─" * term_size().columns, "\x1b[0m\n", sep="")
  35. with suppress(KeyboardInterrupt):
  36. cmd("qmake", "mirage.pro", "CONFIG+=dev")
  37. cmd("make")
  38. cmd("./mirage", "-name", "dev", *args)
  39. if __name__ == "__main__":
  40. if len(sys.argv) > 2 and sys.argv[1] in ("-h", "--help"):
  41. print(__doc__)
  42. else:
  43. (ROOT / "Makefile").exists() and cmd("make", "clean")
  44. run_process(ROOT, run_app, callback=print, watcher_cls=Watcher)