Your problem is less that it’s not valid in OSX (because it very clearly is), but that it doesn’t do what you think it does.
In fact os.system
works just fine, it’s just not opening a terminal window for you because while Windows needs to open a command prompt to run a console application, Unix operating systems (such as Linux or MacOS X) do not. As a result, it’s either giving you an error code or it’s running what you told it to run in the background and you never get to see it.
You need to go a different route for MacOS; you need to first open up a new terminal window using the Terminal application and then tell it to run python (and your script). Below I’ve outlined one way to go about this.
First, we create a shell script which, when when executed, does what I outlined above; open up a new terminal window using the Terminal application, then get it to do something. I saved mine as /Users/tmartin/local/bin/runInTerminal.sh
. Make sure that you make it executable as well via chmod
or however you do that sort of thing using Finder, or things will not work.
#!/bin/sh
osascript - "$@" > /dev/null <<SCRIPT
on run argv
set originalTID to AppleScript's text item delimiters
set AppleScript's text item delimiters to space
tell application "Terminal"
activate
set newTab to do script(argv as text)
end tell
set AppleScript's text item delimiters to originalTID
end run
SCRIPT
As mentioned above, this tells the Terminal application to create a new tab (window) and then uses the rest of the command line arguments as the thing that it tries to execute.
Next, a slightly modified version of the plugin code, which you can save as a python file in your User
package:
import sublime
import sublime_plugin
import os
class RunInTerminalCommand(sublime_plugin.WindowCommand):
def run(self):
script = '/Users/tmartin/local/bin/runInTerminal.sh'
file_name = self.window.active_view().file_name()
command = '{} python {}'.format(script, file_name)
os.system (command)
If you place the shell script above in a place that is on the path, you don’t need to specify the absolute path as I did here. However, since MacOS sets the path differently between GUI and terminal applications and my ~/local/bin
is not in the default path, I didn’t go that route.
Lastly, you just need the key binding; I used this combination, modified from the example to only trigger for a python file, since the plugin is set to only ever run python.
{
"keys": ["ctrl+shift+r"],
"command": "run_in_terminal",
"context": [
{ "key": "selector", "operator": "equal", "operand": "source.python"}
]
},
Note that if you change the python file and don’t save it before you hit the command, it runs the version on disk and not the version in your window which is pretty much guaranteed to send you down a terrible debugging rabbit hole one day.
There are a few solutions to this, such as creating and using a custom build system that runs this script and turning on the “Save All on Build” option, or adding the line below to the command before it executes the script to tell it to save:
self.window.active_view ().run_command ("save")
As an aside this is a rather crude implementation; ideally the plugin code would take arguments that tell it what to run and the key binding would pass them in, so you could use the same command to execute multiple languages. I’ll leave that as an exercise to the reader, though.