Search code examples
svnsublimetext3

Use Sublime Text as SVN side-by-side diff tool


I'm trying to have Sublime Text (3.2.2) be used as SVN diff command (I'm under Scientific Linux). I installed Sublimerge, if I select two files, right-click, select Sublimerge and "Compare Selected Files", the side-by-side view is opened correctly.

Now, if I follow those instrcuctions to try to open the same view to compare a file that changed in a SVN working copy.

I create diff.sh:

#!/bin/bash

/home/prog/sublime-text/sublime_text/sublime_text -n --wait ${6} ${7} --command "sublimerge_diff_views {\"left_read_only\": true, \"right_read_only\": true}"

# Always return 0. There is no way to pass exit code from Sublimerge.
exit 0

When I run svn diff --diff-cmd ./diff.sh myfile Sublime Text is opened and both files are visible in different tabs and no diff is operated.

What am I doing wrong? Is there any way to debug Sublime Text to see what exact command it runs when I do the diff through "Compare Selected Files" menu item and then figure out what could be wrong with my diff.sh script?


Solution

  • The issue you're running into is outlined further down on the page on the integration page for Sublimerge that you posted above, which is:

    ST3: running Sublimerge from command line (only when Sublime Text was not already running) only opens files without doing diff. Otherwise, when launching Sublimerge while ST is running, everything works fine.

    • This is caused by asynchronous plugins loader in ST3 and cannot be fixed from plugin level.

    The issue stems from the fact that in ST3 and up, plugins are executed in an external plugin_host (by contrast, in ST2 the plugin host is built into the core). When Sublime starts it launches the plugin host(s) as separate applications and then reloads session information to set up the window.

    The plugin hosts are responsible for finishing their startup, then loading and activating all of the installed plugins. This is for two main reasons:

    1. It makes Sublime start faster (particularly if you have a few packages with plugins installed) because it starts up and lets you start working while packages are still loading

    2. Should a plugin do something that causes a crash or hang, that happens to the plugin host, leaving Sublime still running; that allows you to save your work and recover, whereas in ST2 it would cause you to lose unsaved changes.

    There's a command line helper named subl (which on Linux is just a symlink/script that executes sublime_text directly, though it's a distinct thing on other platforms) that can be used to interact with Sublime from the command line.

    When you execute subl it hands off what you asked it to do to the running instance of Sublime and then terminates. If Sublime isn't already running, it starts Sublime first before continuing.

    This is an issue for what you're doing here in cases where Sublime isn't already running because subl delivers the command to Sublime right away, but if the plugin host hasn't finished starting up yet the core receives the command but can't execute it because the host isn't ready, so it's ignored.

    To solve the problem, you need to do one of two things:

    • Make sure Sublime is already running
    • Modify the shell script so that it checks to see if sublime_text is currently running; if it is, you can proceed. If not, it needs to start Sublime first and then wait for it to finish before starting the command.

    An example of that is the following:

    #!/bin/bash
    
    # Set up where Sublime is (this could also be on the PATH)
    SUBL=/home/prog/sublime-text/sublime_text/sublime_text 
    
    # If Sublime is not running, start it and wait for plugins to load
    pgrep -x sublime_text > /dev/null
    if [ $? -ne 0 ]; then
        $SUBL
        sleep 2
    fi
    
    # Perform the diff
    $SUBL -n --wait ${6} ${7} --command "sublimerge_diff_views {\"left_read_only\": true, \"right_read_only\": true}"
    
    # Always return 0. There is no way to pass exit code from Sublimerge.
    exit 0
    

    Here we check to see if sublime_text is running or not, and if it's not we pause and delay for 2 seconds before continuing. You want to tune the 2 seconds for your own particular setup.

    To do that, with Sublime not running start it and then check in the console with View > Show Console; plugins aren't fully loaded and activated until you see the text plugins loaded appear in the console. If you have a lot of external packages installed, that could take some time. On faster machines or with fewer external packages, it may be shorter.

    The sleep is given in seconds, but this can be fractional (such as 0.5); you want to fine tune the value to be long enough that it doesn't cause an issue, but short enough that you don't have to wait excessively.