build.py 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. import warnings
  2. import os
  3. import platform
  4. import subprocess
  5. import sys
  6. import time
  7. import threading
  8. # Ignore specific SyntaxWarning
  9. warnings.filterwarnings("ignore", category=SyntaxWarning, module="DrissionPage")
  10. CURSOR_LOGO = """
  11. ██████╗██╗ ██╗██████╗ ███████╗ ██████╗ ██████╗
  12. ██╔════╝██║ ██║██╔══██╗██╔════╝██╔═══██╗██╔══██╗
  13. ██║ ██║ ██║██████╔╝███████╗██║ ██║██████╔╝
  14. ██║ ██║ ██║██╔══██╗╚════██║██║ ██║██╔══██╗
  15. ╚██████╗╚██████╔╝██║ ██║███████║╚██████╔╝██║ ██║
  16. ╚═════╝ ╚═════╝ ╚═╝ ╚═╝╚══════╝ ╚═════╝ ╚═╝ ╚═╝
  17. """
  18. class LoadingAnimation:
  19. def __init__(self):
  20. self.is_running = False
  21. self.animation_thread = None
  22. def start(self, message="Building"):
  23. self.is_running = True
  24. self.animation_thread = threading.Thread(target=self._animate, args=(message,))
  25. self.animation_thread.start()
  26. def stop(self):
  27. self.is_running = False
  28. if self.animation_thread:
  29. self.animation_thread.join()
  30. print("\r" + " " * 70 + "\r", end="", flush=True) # Clear the line
  31. def _animate(self, message):
  32. animation = "|/-\\"
  33. idx = 0
  34. while self.is_running:
  35. print(f"\r{message} {animation[idx % len(animation)]}", end="", flush=True)
  36. idx += 1
  37. time.sleep(0.1)
  38. def print_logo():
  39. print("\033[96m" + CURSOR_LOGO + "\033[0m")
  40. print("\033[93m" + "Building Cursor Keep Alive...".center(56) + "\033[0m\n")
  41. def progress_bar(progress, total, prefix='', length=50):
  42. filled = int(length * progress // total)
  43. bar = '█' * filled + '░' * (length - filled)
  44. percent = f"{100 * progress / total:.1f}"
  45. print(f'\r{prefix} |{bar}| {percent}% Complete', end='', flush=True)
  46. if progress == total:
  47. print()
  48. def simulate_progress(message, duration=1.0, steps=20):
  49. print(f"\033[94m{message}\033[0m")
  50. for i in range(steps + 1):
  51. time.sleep(duration / steps)
  52. progress_bar(i, steps, prefix='Progress:', length=40)
  53. def filter_output(output):
  54. """ImportantMessage"""
  55. if not output:
  56. return ""
  57. important_lines = []
  58. for line in output.split('\n'):
  59. # Only keep lines containing specific keywords
  60. if any(keyword in line.lower() for keyword in ['error:', 'failed:', 'completed', 'directory:']):
  61. important_lines.append(line)
  62. return '\n'.join(important_lines)
  63. def build():
  64. # Clear screen
  65. os.system('cls' if platform.system().lower() == "windows" else 'clear')
  66. # Print logo
  67. print_logo()
  68. system = platform.system().lower()
  69. spec_file = os.path.join("CursorKeepAlive.spec")
  70. if system not in ["darwin", "windows"]:
  71. print(f"\033[91mUnsupported operating system: {system}\033[0m")
  72. return
  73. output_dir = f"dist/{system if system != 'darwin' else 'mac'}"
  74. # Create output directory
  75. os.makedirs(output_dir, exist_ok=True)
  76. simulate_progress("Creating output directory...", 0.5)
  77. # Run PyInstaller with loading animation
  78. pyinstaller_command = [
  79. "pyinstaller",
  80. spec_file,
  81. "--distpath",
  82. output_dir,
  83. "--workpath",
  84. f"build/{system}",
  85. "--noconfirm"
  86. ]
  87. loading = LoadingAnimation()
  88. try:
  89. simulate_progress("Running PyInstaller...", 2.0)
  90. loading.start("Building in progress")
  91. result = subprocess.run(
  92. pyinstaller_command,
  93. check=True,
  94. capture_output=True,
  95. text=True
  96. )
  97. loading.stop()
  98. if result.stderr:
  99. filtered_errors = [line for line in result.stderr.split('\n')
  100. if any(keyword in line.lower()
  101. for keyword in ['error:', 'failed:', 'completed', 'directory:'])]
  102. if filtered_errors:
  103. print("\033[93mBuild Warnings/Errors:\033[0m")
  104. print('\n'.join(filtered_errors))
  105. except subprocess.CalledProcessError as e:
  106. loading.stop()
  107. print(f"\033[91mBuild failed with error code {e.returncode}\033[0m")
  108. if e.stderr:
  109. print("\033[91mError Details:\033[0m")
  110. print(e.stderr)
  111. return
  112. except FileNotFoundError:
  113. loading.stop()
  114. print("\033[91mError: Please ensure PyInstaller is installed (pip install pyinstaller)\033[0m")
  115. return
  116. except KeyboardInterrupt:
  117. loading.stop()
  118. print("\n\033[91mBuild cancelled by user\033[0m")
  119. return
  120. finally:
  121. loading.stop()
  122. # Copy config file
  123. if os.path.exists("config.ini.example"):
  124. simulate_progress("Copying configuration file...", 0.5)
  125. if system == "windows":
  126. subprocess.run(["copy", "config.ini.example", f"{output_dir}\\config.ini"], shell=True)
  127. else:
  128. subprocess.run(["cp", "config.ini.example", f"{output_dir}/config.ini"])
  129. print(f"\n\033[92mBuild completed successfully! Output directory: {output_dir}\033[0m")
  130. if __name__ == "__main__":
  131. build()