ashwinmram's avatar

How to run Laravel Pint on save in Sublime Text 4 on macOS

I still prefer Sublime Text over VS Code because it seems faster, but I couldn't find any package for Pint like the one created for VS Code. I therefore used Chat GPT to learn how to create a plugin :)

  1. Save the following code as pint.py in your Sublime packages directory.
  2. Update the your_username appropriately the herd_directory = '/Users/your_username/Herd' line
  3. When you save a .php file, this should trigger pint to run on the file.
import sublime
import sublime_plugin
import subprocess
import os

class TerminalOnSave(sublime_plugin.EventListener):
    def on_post_save(self, view):
        file_name = view.file_name()

        # Check if it's the file you want to trigger on save
        if file_name.endswith('.php'):
            # Get the current file's path
            file_path = view.file_name()

            # Specify the common parent directory (Herd directory)
            herd_directory = '/Users/your_username/Herd'

            # Get the relative path from the Herd directory
            relative_path = os.path.relpath(file_path, herd_directory)

            # Get the base folder under the Herd directory
            base_folder = os.path.join(herd_directory, relative_path.split(os.path.sep)[0])

            # Run your terminal command with iTerm in the same window
            script = f'tell application "iTerm"\n'
            script += f'tell current session of current window to write text "cd {base_folder} && ./vendor/bin/pint {file_path}"\n'
            script += 'end tell'

            subprocess.run(['osascript', '-e', script])
0 likes
3 replies
LaryAI's avatar
Level 58

The provided script is a good starting point for running Laravel Pint on save in Sublime Text 4. However, there are a few improvements and clarifications that can be made to ensure it works correctly.

Firstly, the script uses AppleScript to send commands to iTerm, which is macOS-specific. This means it won't work on other operating systems. Additionally, the script hardcodes the project directory, which is not ideal if you work with multiple Laravel projects.

Here's an improved version of the script that uses the built-in terminal and dynamically determines the project root directory by looking for the artisan file, which is unique to Laravel projects:

import sublime
import sublime_plugin
import subprocess
import os

class LaravelPintOnSaveCommand(sublime_plugin.EventListener):
    def on_post_save(self, view):
        file_name = view.file_name()

        # Check if it's a PHP file
        if file_name.endswith('.php'):
            # Find the Laravel project root by looking for the artisan file
            directory = self.find_project_root(file_name)

            if directory:
                # Run Pint from the project root
                command = f'cd "{directory}" && ./vendor/bin/pint "{file_name}"'
                subprocess.run(command, shell=True, check=True)

    def find_project_root(self, file_path):
        # Start with the directory of the current file
        current_dir = os.path.dirname(file_path)

        # Traverse up the directory tree to find the Laravel project root
        while current_dir != os.path.dirname(current_dir):  # Stop at the root directory
            if os.path.isfile(os.path.join(current_dir, 'artisan')):
                # Found the Laravel project root
                return current_dir
            else:
                # Move up one directory
                current_dir = os.path.dirname(current_dir)

        # Laravel project root not found
        return None

To use this script:

  1. Save the script as pint.py in your Sublime Text packages directory. You can find this directory by going to Sublime Text > Preferences > Browse Packages... in the menu.

  2. Ensure that Laravel Pint is installed in your Laravel project by running composer require laravel/pint --dev if you haven't already.

  3. Now, every time you save a .php file, the script will attempt to find the Laravel project root by looking for the artisan file. If it finds the project root, it will run Pint on the saved file.

Remember that this script assumes you have PHP and Laravel Pint installed and available in your system's PATH. If you have a different setup, you may need to adjust the command accordingly.

1 like
hsl's avatar

@LaryAI Have you ever run into an error like this?

Traceback (most recent call last):
  File "/Applications/Sublime Text.app/Contents/MacOS/Lib/python38/sublime_plugin.py", line 934, in on_post_save
    run_view_callbacks('on_post_save', view_id)
  File "/Applications/Sublime Text.app/Contents/MacOS/Lib/python38/sublime_plugin.py", line 741, in run_view_callbacks
    callback(v, *args)
  File "/Applications/Sublime Text.app/Contents/MacOS/Lib/python38/sublime_plugin.py", line 162, in profiler
    return event_handler(*args)
  File "/Users/<username>/Library/Application Support/Sublime Text/Packages/User/pint.py", line 18, in on_post_save
    subprocess.run(command, shell=True, check=True)
  File "./python3.8/subprocess.py", line 516, in run
subprocess.CalledProcessError: Command 'cd "/Users/<username>/Projects/<project-name>" && ./vendor/bin/pint "/Users/<username>/Projects/<project-name>/app/Http/Controllers/AdminController.php"' returned non-zero exit status 127.
ashwinmram's avatar

I had hardcoded my project folder in the original post, which I edited after Lary's comment. The script in the original post now works perfectly at the time of this writing assuming:

  1. You are using macOS and iTerm
  2. You are using Laravel Herd
  3. Laravel Pint is included in your project
1 like

Please or to participate in this conversation.