Home Download Buy Blog Forum Support

Beta Plugin to send/run selected code in R, Stata or iTerm

Beta Plugin to send/run selected code in R, Stata or iTerm

Postby gregor.hoch on Mon Oct 03, 2011 6:24 pm

Hi, I just wrote a small Mac OS plugin that takes the selected code and sends it to R, Stata or iTerm. Any suggestions are welcome. SendSelectionCommand calls R or stata depending on the extension of the file and SendSelectionIterm always sends stuff to iterm (I am using this for cloud computing).
I will work with this for a while and put it on the plugin list when there are no bugs...

R, and iTerm work flawlessly. Stata is a little annoying because you first have to save the code in a file and then open the .do file with Stata. Doing this, however, changes the stata working directory. Currently, I call a second file which just runs "cd '$job'" to change to the working dir to the global $job. So if you define such a global, stata always changes back. Suggestions for alternative implementations are welcome! You might also have to change 'StataMP' to 'StataSE' depending on the version of stata you have.

Key bindings
Code: Select all
{ "keys": ["super+e"], "command": "send_selection" },
{ "keys": ["super+shift+e"], "command": "send_selection_iterm" }

Send-Selection.py (copy to /Packages/User)
Code: Select all
import sublime, sublime_plugin
import os, subprocess, string

#https://sites.google.com/site/josefmontag/programs
# to test strings:

#self.view.insert(edit, 0, cmd)


class SendSelectionCommand(sublime_plugin.TextCommand):   
   def run(self, edit):
      # get selection   
      selection = ""
      for region in self.view.sel():
         selection+=self.view.substr(region) + "\n"

      # only proceed if selection is not empty
      if(selection!="\n"):
         extension = os.path.splitext(self.view.file_name())[1]

         # R file
         if(extension.lower()==".r"):
            # define osascript command
            cmd = """osascript -e 'tell app "R" to activate' """
            cmd+= """-e 'tell app "R" to cmd \"""" + string.replace(selection,"\"","\\\"") + """\"' """
            # run and reactivate Sublime Text 2
            os.system(cmd)
            subprocess.Popen("""osascript -e 'tell app "Sublime Text 2" to activate' """, shell=True)

         # Stata file
         if(extension.lower()==".do"):
            # define location of do file
            file=sublime.packages_path() + "/User/sublime2stata.do"
            file_restore=sublime.packages_path() + "/User/sublime2stata_restore.do"
            # copy selection into file
            os.system("echo '" + selection + "' > '" + file + "'")
            os.system("""echo 'qui cd \"$job\"' > '""" + file_restore + "'")
            # define osascript command and run
            cmd_run = """osascript -e 'tell app "StataMP" to activate' """
            cmd_run+= """-e 'tell app "StataMP" to open POSIX file \"""" + file + """\"' """
            cmd_run+= """-e 'tell app "StataMP" to open POSIX file \"""" + file_restore + """\"' """
            os.system(cmd_run)
#            os.system("rm '" + file + "'")
#            os.system("rm '" + file_restore + "'")

            # restore stata working directory from global $job
            subprocess.Popen("""osascript -e 'tell app "Sublime Text 2" to activate' """, shell=True)


class SendSelectionItermCommand(sublime_plugin.TextCommand):   
   def run(self, edit):
      selection = ""
      for region in self.view.sel():
         selection+=self.view.substr(region) + "\n"
      
      if(selection!="\n"):
         # define location of shell script with selection as argument
         script="sh '" + sublime.packages_path() + "/User/send-selection-iterm.sh' \"" + string.replace(selection,"\"","\\\"") + "\""
         # run shell script and reactivate Sublime Text 2
         os.system(script)
         subprocess.Popen("""osascript -e 'tell app "Sublime Text 2" to activate' """, shell=True)


shell script for iTerm: send-selection-iterm.sh (copy to /Packages/User)
Code: Select all
#!/bin/sh

PASTE=$(echo "$@" | sed 's/\/\//*/g' | sed 's/\"/\\\"/g'  | sed 's/   //g' | sed -n '1h
1!{
        # if the sought-after regex is not found, append the pattern space to hold space
        /\/\*.*\*\// !H
        # copy hold space into pattern space
        g
        # if the regex is found, then...
        /\/\*.*\*\// {
                # the regular expression
                s/\/\*.*\*\// /g
                # print
                p
                # read the next line into the pattern space
                n
                # copy the pattern space into the hold space
                h
        }
        # copy pattern buffer into hold buffer
        h
}
# if the last line then print
$p
')


osascript << END
tell application "iTerm"
   activate
   tell current terminal
      tell current session
         write text "$PASTE"
      end tell
   end tell
end tell
#tell application "Sublime Text 2"
#   activate
#end tell
#END
gregor.hoch
 
Posts: 128
Joined: Sat Oct 01, 2011 7:54 pm

Re: Beta Plugin to send/run selected code in R, Stata or iTerm

Postby gregor.hoch on Thu Oct 06, 2011 8:03 pm

There doesn't really seem to be a lot of interest but this HAS TO work flawlessly to get people from the statistics community interested in ST
So here is an update...
I am sure there are better ways to do this (presumably directly from Python) but I build on my existing shell scripts from Textmate. Currently, these scripts fail when there are backslashes in the code you want to send... :(

Code: Select all
import sublime, sublime_plugin
import os, subprocess, string, pipes

class SendSelectionCommand(sublime_plugin.TextCommand):   
   @staticmethod
   def cleanString(str):
      #str=string.replace(str,'\\','\\\\')
      str=string.replace(str,'"','\\"')      
      return str

   def run(self, edit):
      # get selection   
      selection = ""
      for region in self.view.sel():
         selection+=self.view.substr(region) + "\n"
      selection = (selection[::-1].replace('\n'[::-1], '', 1))[::-1]

      # only proceed if selection is not empty
      if(selection!=""):
         extension = os.path.splitext(self.view.file_name())[1]

         # R file
         if(extension.lower()==".r"):
            cmd = 'osascript<<-END\n'
            cmd+= '  tell app "R"\n'
            cmd+= '  activate\n'
            selection=self.cleanString(selection).split("\n")
            for part in selection:
               cmd+= '  cmd "' + part + '"\n'               
            cmd+= '  end tell\nEND'         
            self.view.insert(edit, 0, cmd)      
            os.system(cmd)
            subprocess.Popen("""osascript -e 'tell app "Sublime Text 2" to activate' """, shell=True)

         # Stata file
         if(extension.lower()==".do"):
            # define location of do file
            file=sublime.packages_path() + "/User/sublime2stata.do"
            file_restore=sublime.packages_path() + "/User/sublime2stata_restore.do"
            # copy selection into file
            os.system("echo '" + selection + "' > '" + file + "'")
            os.system("""echo 'qui cd \"$job\"' > '""" + file_restore + "'")
            # define osascript command and run
            cmd_run = """osascript -e 'tell app "StataMP" to activate' """
            cmd_run+= """-e 'tell app "StataMP" to open POSIX file \"""" + file + """\"' """
            cmd_run+= """-e 'tell app "StataMP" to open POSIX file \"""" + file_restore + """\"' """
            os.system(cmd_run)

            # restore stata working directory from global $job
            subprocess.Popen("""osascript -e 'tell app "Sublime Text 2" to activate' """, shell=True)


class SendSelectionIterm(sublime_plugin.TextCommand):   
   @staticmethod
   def cleanString(str):
      str=string.replace(str,'\\','\\\\')
      str=string.replace(str,"\"","\\\"")
      str = (str[::-1].replace('\n'[::-1], '', 1))[::-1]
      return str

   def run(self, edit):
      selection = ""
      for region in self.view.sel():
         selection+=self.view.substr(region) + "\n"
      selection=self.cleanString(selection)
      
      if(selection!="\n"):
         # define location of shell script with selection as argument
         script='sh "' + sublime.packages_path() + '/User/send-selection-iterm.sh" "' + selection + '"'
         # run shell script and reactivate Sublime Text 2
         os.system(script)
         subprocess.Popen("""osascript -e 'tell app "Sublime Text 2" to activate' """, shell=True)

gregor.hoch
 
Posts: 128
Joined: Sat Oct 01, 2011 7:54 pm

Re: Beta Plugin to send/run selected code in R, Stata or iTerm

Postby bblue on Sat Oct 15, 2011 9:37 pm

Hi gregor!

I'm very interested in your nice work.
Please, keep it up!

:-)

--
bblue
bblue
 
Posts: 24
Joined: Mon Oct 10, 2011 10:35 am

Re: Beta Plugin to send/run selected code in R, Stata or iTerm

Postby gregor.hoch on Thu Oct 20, 2011 4:51 pm

Here is an update to the SendSelection function that should work for R with almost all code (special characters, quotes etc). The previous version had some serious problems with certain special characters...


Code: Select all
class SendSelectionCommand(sublime_plugin.TextCommand):   
   @staticmethod
   def cleanString(str):
      str=string.replace(str,'"','\\"')
      return str

   def run(self, edit):
      # get selection   
      selection = ""
      for region in self.view.sel():
         selection+=self.view.substr(region) + "\n"
      selection = (selection[::-1].replace('\n'[::-1], '', 1))[::-1]

      # only proceed if selection is not empty
      if(selection!=""):
         extension = os.path.splitext(self.view.file_name())[1]

         # R file
         if(extension.lower()==".r"):
            # define list of arguments
            args=['osascript','-e','tell app "R" to activate']
            # split selection into lines
            selection=self.cleanString(selection).split("\n")
            # add code lines to list of arguments
            for part in selection:
               args.extend(['-e', 'tell app "R" to cmd "' + part + '"\n'])
            # execute code and activate ST2
            p = subprocess.Popen(args)
            subprocess.Popen("""osascript -e 'tell app "Sublime Text 2" to activate' """, shell=True)

            # args=['osascript','-e','tell app "R" to activate','-e',"""tell app "R" to cmd "cty.data$\\"terror1980d\\"" """]
            # p = subprocess.Popen(args)
            #subprocess.Popen("""osascript -e 'tell app "Sublime Text 2" to activate' """, shell=True)

         # Stata file
         if(extension.lower()==".do"):
            # define location of do file
            file=sublime.packages_path() + "/User/sublime2stata.do"
            file_restore=sublime.packages_path() + "/User/sublime2stata_restore.do"
            # copy selection into file
            os.system("echo '" + selection + "' > '" + file + "'")
            os.system("""echo 'qui cd \"$job\"' > '""" + file_restore + "'")
            # define osascript command and run
            cmd_run = """osascript -e 'tell app "StataMP" to activate' """
            cmd_run+= """-e 'tell app "StataMP" to open POSIX file \"""" + file + """\"' """
            cmd_run+= """-e 'tell app "StataMP" to open POSIX file \"""" + file_restore + """\"' """
            os.system(cmd_run)
#            os.system("rm '" + file + "'")
#            os.system("rm '" + file_restore + "'")

            # restore stata working directory from global $job
            subprocess.Popen("""osascript -e 'tell app "Sublime Text 2" to activate' """, shell=True)
gregor.hoch
 
Posts: 128
Joined: Sat Oct 01, 2011 7:54 pm

Re: Beta Plugin to send/run selected code in R, Stata or iTerm

Postby gregor.hoch on Thu Oct 20, 2011 5:58 pm

Also add the line
Code: Select all
str=string.replace(str,'\\','\\\\')

to the cleanString function.

Here is the same function for iTerm

Code: Select all
class SendSelectionIterm(sublime_plugin.TextCommand):   
   @staticmethod
   def cleanString(str):
      str=string.replace(str,'\\','\\\\')
      str=string.replace(str,'"','\\"')      
      return str
   
   def run(self, edit):
      selection = ""
      for region in self.view.sel():
         selection+=self.view.substr(region) + "\n"
      selection = (selection[::-1].replace('\n'[::-1], '', 1))[::-1]      

      # only proceed if selection is not empty
      if(selection!=""):
         extension = os.path.splitext(self.view.file_name())[1]

         # define list of arguments
         args=['osascript','-e','tell app "iTerm" to activate']
         # split selection into lines
         selection=self.cleanString(selection).split("\n")
         # add code lines to list of arguments
         for part in selection:
            args.extend(['-e', 'tell app "iTerm" to tell current terminal to tell current session to write text "' + part + '"\n'])
         # execute code and activate ST2
         p = subprocess.Popen(args)
         subprocess.Popen("""osascript -e 'tell app "Sublime Text 2" to activate' """, shell=True)
gregor.hoch
 
Posts: 128
Joined: Sat Oct 01, 2011 7:54 pm

Re: Beta Plugin to send/run selected code in R, Stata or iTerm

Postby maiasaura on Mon Dec 19, 2011 3:00 am

I just started using sublime text a few hours ago. I am a statistician and use R. Where exactly do I copy these functions?
Into a separate file in my packages/R folder?
or do I paste the function into one of my user settings files?

thanks
maiasaura
 
Posts: 15
Joined: Mon Dec 19, 2011 2:31 am

Re: Beta Plugin to send/run selected code in R, Stata or iTerm

Postby C0D312 on Mon Dec 19, 2011 3:11 am

This is a plugin, so you can go: Tools > New Plugin. Copy and paste the code. Save the file in your User folder (Packages > User should be the default folder open when you press save as).
C0D312
 
Posts: 1063
Joined: Sun Jul 10, 2011 3:23 am

Re: Beta Plugin to send/run selected code in R, Stata or iTerm

Postby maiasaura on Wed Jan 04, 2012 9:33 pm

I managed to make it work. The downside is that it wont send any selection to R unless i save the file as something.r
This sucks because I often test chunks of code that I don't write to disk (so I'll use an unsaved file) but there seems no way around it.
maiasaura
 
Posts: 15
Joined: Mon Dec 19, 2011 2:31 am

Re: Beta Plugin to send/run selected code in R, Stata or iTerm

Postby maiasaura on Thu Jan 26, 2012 10:33 pm

I see someone already updated the plugin to account for odd string behavior -- thanks.
maiasaura
 
Posts: 15
Joined: Mon Dec 19, 2011 2:31 am

Re: Beta Plugin to send/run selected code in R, Stata or iTerm

Postby maiasaura on Fri Feb 03, 2012 1:39 am

Anyone have ideas on how to make this work on multi line selections? For some reason it only works if I select one line at a time.
thanks
maiasaura
 
Posts: 15
Joined: Mon Dec 19, 2011 2:31 am

Next

Return to Plugin Development

Who is online

Users browsing this forum: No registered users and 9 guests

cron