Hi,
I looked at the R-bundle command 'Execute Line / Selection'.
I rewrote this command to improve it and fasten it a bit, at least in my eyes.
Changes for this command and for the language grammar 'R console': 1) I compiled the AppleScript and saved it as 'Run only'. This is a bit faster. Furthermore within this script I use the clipboard to pass the command to R, and I also get back R's result via the clipboard. This has a nice side-effect for the encoding problems: Example: If I type 'print("Immer Ärger mit Jörg")' I will get back '[1] "Immer √Ñrger mit J√∂rg"' with the 'old' version caused by the UTF-8 encoding. If I do it via the clipboard then it outputs the string correctly, but if you have a look at R.app you see weird characters. And finally I took care about the AppleScript file size, because it remembers the the 'oldtext' and 'text_area'. So, I set these variables to "" and the end.
Of course, to use the clipboard will destroy its content, but this can be discussed.
To work with the AppleScript tm_get_r.scpt you have to copy the attached script to R-bundle's /Support/bin folder, or you can compile it by yourself.
2) If you have a TM window set to R console scope, and you enter a command like '> 3*3' the script now is checking whether R.app is running. If not it opens it, waits 5 seconds, hides R.app, and sends the command to R.
3) I changed the language grammar for 'R console' to be able to do the following: I type '4+' press ENTER, R returns '+ ' to complete my command. If you type now '4' the old grammar ignores that. So I changed the line 'begin = ...' within the grammar to: ________________ { scopeName = 'source.r-console'; fileTypes = ( ); patterns = ( { name = 'source.r.embedded.r-console'; begin = '^[>|+] '; end = '\n|\z'; beginCaptures = { 0 = { name = 'punctuation.section.embedded.r- console'; }; }; patterns = ( { include = 'source.r'; } ); }, ); } ________________
Now you can type as usual.
4) If R asks for an user input via 'readline' you can't just type the answer and press ENTER because TM's command expects '> ' or '+ ' at the beginning of the line. To solve it here's a suggestion: If the last line of R's return is not '> ' or '+ ' I insert '\n> '. It is not standard but now you can type the answer straightforward.
5) I suppressed any error message coming from AppleScript. E.g., if you type '?C' and R.app is not running, R starts, and shows the help, but meanwhile AppleScript wants to have the content, but it does not get it. Thus AppleScript outputs an error, but there is no error. In such a case R's return is nothing and by using the suggestion of 4) you have a '> ' and no error message at the last line in TM.
6) I only changed the code, not the input/output settings.
######### Here comes the new code for 'Execute Line /Selection':
__________________ echo echo -e `tail -c+2` | pbcopy
# check whether R.app is running if [ $(ps -xc | grep ' R$' | wc -l) -eq 0 ]; then open -a R # sleeps for 5 sec - can be fine-tuned sleep 5 osascript <<-AS tell application "System Events" set visible of process "R" to false end tell AS fi
osascript "$TM_BUNDLE_SUPPORT/bin/tm_get_r.scpt" &>/dev/null
RES=$(pbpaste | tail -n +2) echo -en "$RES"
NL=$(echo -en "$RES" | tail -n 1) if [ "$NL" != "> " -a "$NL" != "+ " ]; then echo -en "\n> " fi
########################################## # source code for 'tm_get_r' # # # tell application "System Events" # -- Get a reference to the text field # set text_area to (process "R")'s (window "R Console")'s (scroll area 1)'s text area 1 # # -- Get text before and after our command # set oldtext to text_area's value # tell application "R" to cmd (the clipboard) # set newtext to text_area's value # # -- Find the difference between old and new # set the clipboard to text from ((oldtext's length) + 1) to -1 of newtext # set oldtext to "" # set newtext to "" # set text_area to "" # end tell # ########################################### _________________________
Any comments?
Is there someone who is quasi responsible for this bundle?
All the best,
Hans
On Dec 15, 2006, at 4:09 PM, Hans-Joerg Bibiko wrote:
Of course, to use the clipboard will destroy its content, but this can be discussed.
Yeah this is really not acceptable. Perhaps there is a way to write the information in some sort of temp file, or an unnamed pipe? (I think there is some trick with something like "<(commandshere)" that you can add to the end of a command, so that the output of commandshere is fed as a filename would have been fed otherwise, or something line that). We do need a way to get things to go back and forth without touching the clipboard. The clipboard is the user's space, we shouldn't be messing with it without the user asking for it.
Haris
Hi,
Of course, to use the clipboard will destroy its content, but this can be discussed.
Yeah this is really not acceptable. Perhaps there is a way to write the information in some sort of temp file, or an unnamed pipe? (I think there is some trick with something like "<(commandshere)" that you can add to the end of a command, so that the output of commandshere is fed as a filename would have been fed otherwise, or something line that). We do need a way to get things to go back and forth without touching the clipboard. The clipboard is the user's space, we shouldn't be messing with it without the user asking for it.
Yes, yes I know the clipboard is the user's territory. To restore the old clipboard content is doable but you destroy TM history list. It was ONLY a suggestion because it made things easier and fast ;)
So, to avoid the clipboard and speed up the AppleScript a bit I found this:
Command 'Execution Line/Selection' _________________________ echo TASK=`tail -c +2`
# check whether R.app is running if [ $(ps -xc | grep ' R$' | wc -l) -eq 0 ]; then open -a R # sleeps for 5 sec - can be fine-tuned sleep 5 osascript <<-AS tell application "System Events" set visible of process "R" to false end tell AS fi
RES=$(osascript "$TM_BUNDLE_SUPPORT/bin/tm_get_r.scpt" "$TASK" 2>/dev/ null | tail -n +2)
echo -en "$RES"
NL=$(echo -en "$RES" | tail -n 1) if [ "$NL" != "> " -a "$NL" != "+ " ]; then echo -en "\n> " fi
########################################## # source code for 'tm_get_r' # # #on run (argv) # tell application "System Events" # -- Get a reference to the text field # set text_area to (process "R")'s (window "R Console")'s (scroll area 1)'s text area 1 # -- Get text before and after our command # set oldtext to text_area's value # set x to item 1 of argv # tell application "R" to cmd x # set newtext to text_area's value # # -- Find the difference between old and new # text from ((oldtext's length) + 1) to -1 of newtext # end tell #end run # ########################################### __________________________
The tricky thing is to pass parameters to AppleScript. I've chosen the variant via an argument list. I tried to get the command via AppleScript's "system attribute" but I found no way to export the variable TASK in such a way that the AppleScript will find it.
The new command has the same features like the variant using the clipboard.
The nice thing with the clipboard also was that I don't have encoding problem like print("façade") but maybe I find a fast way to solve it.
Attached is the compiled AppleScript, the sourde code you find above.
Please check this command for bugs or improvements. I did a tiny benchmark test and it turns out that this command is about 35% faster than the variant with embedded AppleScript.
Cheers, -Hans
PS You have to copy this compiled file into R bundle's /Support/bin folder. (Or compile it by yourself)