Monday, July 23, 2018
  • Index
  •  » Code Exchange
  •  » Making a compile Script for BareBones Editor with Results browser.

#1 2014-02-19 02:36:35 am

McUsrII
Member
Registered: 2012-11-21
Posts: 3046
Website

Making a compile Script for BareBones Editor with Results browser.

Hello

Just for the record.
Another title would have been: Enter the Dragon! Access Clang from BBEdit or TextWrangler.

This script shows how to script a results browser of TextWrangler or BBEdit, by the simples means possible.

The script in itself is useful, if you'd like to compile Foundation examples, and see how they run from outside Xcode, as you may have a project there (or several), that you are working on.

So, if there are errors in the .m file, then a Results Browser window is thrown up as the front window of your BareBones Editor of choice. Otherwise, you are presented with the foreground Terminal window, (one is created if none exists), and your compiled example code is executed there.

Here is the script, you should really call it Compile Obj-C
After you have installed it, and assigned cmd-R as the short cut key, then use the file below to verify that it works.

Edit
And when you have affirmed that you are getting up the results browser, then please fix some of the errors, and see that you indeed get the executable running in terminal.

Applescript:


-- Copyright © 2014 McUsr All Rights Reserved.
# This script compiles an Objective-C file from BBEdit or TextWrangler
# The Objective-C file is intended to use the Foundation framework only.
# if you want to compile other stuff, then you'll have to configure the
# command line


tell application "BBEdit"
save text document 1
set sourceFile to file of text document 1
end tell

tell (a reference to text item delimiters)
set {tids, contents of it} to {contents of it, ":"}
set pieces to text items of (sourceFile as string)
set sourceFileName to the last text item of pieces
set contents of it to "/"
set sourceFileFolder to "/" & text items 2 thru -2 of pieces as text
set contents of it to tids
end tell
# we compile the file here, we redirect any standard error, and we amend the
# exit code of the comple-commandto the output, so that we understand what
# path to take
set compileScript to "cd " & (quoted form of sourceFileFolder) & "; clang -fobjc-arc -framework Foundation -Weverything " & quoted form of sourceFileName & " -o a.out 2>&1; echo $?"
set compilerOutput to paragraphs of (do shell script compileScript)

try
set exitCode to item -1 of compilerOutput as number
on error
display alert "Something is wrong with the compile script Aborting."
error number -128
end try

if exitCode = 0 then
# Time to run the command in a terminal window. to see some results :)
tell application "Terminal"
activate
set shell_script to "cd " & (quoted form of sourceFileFolder) & " ; a.out "
if (count windows) is 0 then
do script shell_script
else
do script shell_script in the front window
end if
end tell
else
set locationPars to {}
# we fire up a results browser in the app, so that we can see the errors.
repeat with anErrorLine in compilerOutput
set locationText to do shell script "sed -n '/.*[:][1-9]*[:][1-9]*.*[:].*/p' <<<" & quoted form of anErrorLine
if locationText is not "" then set end of locationPars to locationText
end repeat

set locationData to {}
repeat with aLocPar in locationPars
tell (a reference to text item delimiters)
set {tids, contents of it} to {contents of it, ":"}
set pieces to text items of aLocPar
set err_msg to the last text item of pieces
set lineNmbr to text item 2 of pieces
set theFname to text item 1 of pieces
set contents of it to tids
end tell
copy {err_msg, theFname, lineNmbr} to end of locationData
end repeat

tell application "BBEdit"
set resultItems to {}
repeat with location in locationData

set {locationMessage, locationFile, locationLine} to location

set hits to (text documents whose on disk is true and URL contains locationFile)
if (count of hits) > 0 then
set mydoc to first item of hits
set locationLine to locationLine as number
set myline to line locationLine of mydoc
set s_offset to characterOffset of myline
if (count of characters of myline) > 0 then
set e_offset to characterOffset of last character of myline
else
set e_offset to s_offset
end if
set resultEntry to {start_offset:(s_offset - 1), end_offset:e_offset, message:locationMessage, result_kind:error_kind, result_file:file of mydoc, result_line:locationLine}
copy resultEntry to end of resultItems
end if

end repeat

make new results browser with data resultItems with properties {name:"Compile Errors in " & sourceFileName}
end tell
end if

[code]#import <Foundation/Foundation.h>
int main(int argc, const char * argv[])
{
    @autoreleasepool {
         NSLog(@"Hello World");
         NSInteger myint = "Stunned"
     }
     return 0;
}[/code]
Enjoy.

Last edited by McUsrII (2014-02-19 02:50:50 am)

Offline

 

#2 2014-02-19 01:39:20 pm

druido
Member
Registered: 2010-09-03
Posts: 101

Re: Making a compile Script for BareBones Editor with Results browser.

Thanks for posting this! I have a similar script for compiling C++ files, but I am sending compilers's errors to a new TextWrangler document, which I don't like much. I hadn't thought of using a results browser: that's really cool! I plan to take a closer look at your code and I hope to be able to use it with C++ (where error messages can be of biblical length, especially when using templates).

I suggest two improvements to your script (OS X 10.9 only):

1) display a notification when compilation is successful, along these lines (untested code):

Applescript:


-- [...]
if compilerOutput is not equal to "" then
set notificationText to "There are some warnings."
else
set notificationText to "No issues."
end if
display notification notificationText with title "Build succeeded" subtitle sourceFileName

2) add a progress bar using a script library (which you can put inside your script bundle), so that there is some feedback when the code is compiling. You may use Shane Stanley's excellent example code.

Offline

 

#3 2014-02-19 03:31:22 pm

McUsrII
Member
Registered: 2012-11-21
Posts: 3046
Website

Re: Making a compile Script for BareBones Editor with Results browser.

Hello.

Thank you for the feedback.

The reason that I code the extraction of comments that way is to cut off the line below, showing exactly where there is something wrong by pointing ^^^^^ below it. It is an approach that works well with Clang, or so it seems.

I made this for small snippets, or "single-file" stuff, so I'll be there when I see either the executable running, or get The Results Browser in my face. I don't see a need for notification.

And for larger C-Based project, I use(d) Vim and make files. I think you can use this with makefiles as well, tailor it too your needs as you see fit. -And you can use the Results Browser for all kinds of parsing, given that you get some line numbers and error messages. This is really the reason (together with BBEdi'ts easy to create and use templates) that I implemented the environment in one of those. The Results Browser is a really cool tool, once you get your head around it.

But my preferred Development Environment is of course Xcode, I haven't words for how good it is really. smile

Edit

I actually have some words for what I feel about Xcode, and that is that it is as hot-dirty-sexy as Cocoa and Objective-C. smile -But you have to invest some time in it.

Last edited by McUsrII (2014-02-19 03:41:04 pm)

Offline

 

#4 2014-02-19 10:26:45 pm

McUsrII
Member
Registered: 2012-11-21
Posts: 3046
Website

Re: Making a compile Script for BareBones Editor with Results browser.

Hello.

I see the need for output while something is compiling if you are going to compile more than something that takes merely milliseconds, and actually, even then it would be nice with some feedback.

I figure the best way to do this, is to create a temporary fil in the script, and the executing the Clang  command line, in the terminal window, so you get any stats and so on, and see that stuff is actually happening, teeing the output to a temporary file as well. This scheme lets you also keep the previous output in the terminal window. -This feature is not so important for me, but I will at some time at my own leisure upgrade it to show this output, and also to assure that the front terminal window is indeed dedicated to the same directory as where the files are compiled.

I have just assured that the tee command will suffice and that it is no need for mkpipe. smile



*

I believe Clang is the English name of the dragon that Bilbo Baggins met in "The Hobbit"

Offline

 

#5 2014-02-20 04:12:35 pm

McUsrII
Member
Registered: 2012-11-21
Posts: 3046
Website

Re: Making a compile Script for BareBones Editor with Results browser.

This version Reflects the output of clang from the Terminal window into the
Results Browser of BBEdit or TextWrangler (see above). This as a meaningful way of showing progres during longer compilers. Thanks to druido for commenting on that.

This version also differs between errors and warnings in the compiler window.

Some speed improvements.

Edit

I had to add some parenthesis around the do shell script line that "cats back" the output for some wicked reason.

Applescript:

-- [url]http://macscripter.net/viewtopic.php?pid=171134#p171134[/url]
-- ( I have -Werror enabled).
# This script compiles an Objective-C file from BBEdit or TextWrangler
# The Objective-C file is intended to use the Foundation framework only.
# if you want to compile other stuff, then you'll have to configure the
# command line
(*
20.02.14T22:52:04

New model, "reflects" the output from the terminal window into
the results browser, as a meaningful way of showing progress.
-> if error from compile, otherwise executes a.out

21.02.14T00:27:51

Added some more robustness, when parsing the result code of the compile.
*)

main()
on main()
   tell application "BBEdit"
       close every results browser
       save text document 1
       set sourceFile to file of text document 1
       try
           tell me to do shell script "rm ~/Library/Caches/net.mcusr.Clang-result.tmp "
       end try
   end tell
   
   tell (a reference to text item delimiters)
       set {tids, contents of it} to {contents of it, ":"}
       set pieces to text items of (sourceFile as string)
       set sourceFileName to the last text item of pieces
       set contents of it to "/"
       set sourceFileFolder to "/" & text items 2 thru -2 of pieces as text
       set contents of it to tids
   end tell
   # we compile the file here, we redirect any standard error, and we amend the
   # exit code of the comple-commandto the output, so that we understand what
   # path to take
   set compileScript to "cd " & (quoted form of sourceFileFolder) & "; ( clang -fobjc-arc -framework Foundation -Weverything " & quoted form of sourceFileName & " -o a.out 2>&1 ; echo $? )| /usr/bin/tee ~/Library/Caches/net.mcusr.Clang-result.tmp "
   # We tee the file, an preserve the error code, so that we show the output in the front terminal window, (and can see progress)
   tell application "Terminal"
       activate
       if (count windows) is 0 then
           do script compileScript
       else
           do script compileScript in the front window
       end if
   end tell
   delay 1
   set compileroutput to (do shell script "/bin/cat ~/Library/Caches/net.mcusr.Clang-result.tmp" without altering line endings)
   try
       set exitCode to paragraph -2 of compileroutput as number
       
   on error
       try
           set exitCode to paragraph -1 of compileroutput as number
       on error
           display alert "Something is wrong with the compile script Aborting."
           error number -128
       end try
   end try
   if exitCode = 0 then
       # Time to run the command in a terminal window. to see some results :)    
       tell application "Terminal"
           activate
           set shell_script to "cd " & (quoted form of sourceFileFolder) & " ; a.out "
           if (count windows) is 0 then
               do script shell_script
           else
               do script shell_script in the front window
           end if
       end tell
   else
       set locationPars to paragraphs 1 thru -2 of (do shell script "sed -n '/.*[:][1-9]*[:][1-9]*.*[:].*/p' <<<" & quoted form of compileroutput without altering line endings)
       script f
           property locationData : {}
       end script
       
       repeat with aLocPar in locationPars
           tell (a reference to text item delimiters)
               set {tids, contents of it} to {contents of it, ":"}
               set pieces to text items of aLocPar
               set err_msg to the last text item of pieces
               set errorType to words of item 4 of pieces
               set lineNmbr to text item 2 of pieces
               set theFname to text item 1 of pieces
               set contents of it to tids
           end tell
           copy {theFname, lineNmbr, errorType, err_msg} to end of f's locationData
       end repeat
       log f's locationData
       tell application "BBEdit"
           set resultItems to {}
           repeat with i from 1 to (count f's locationData)
               
               set {locationFile, locationLine, errorType, locationMessage} to item i of f's locationData
               
               set hits to (text documents whose on disk is true and URL contains locationFile)
               if (count of hits) > 0 then
                   set mydoc to first item of hits
                   set locationLine to locationLine as number
                   set myline to line locationLine of mydoc
                   set s_offset to characterOffset of myline
                   if (count of characters of myline) > 0 then
                       set e_offset to characterOffset of last character of myline
                   else
                       set e_offset to s_offset
                   end if
                   if errorType contains "warning" then
                       set eType to warning_kind
                   else
                       set eType to error_kind
                   end if
                   set resultEntry to {start_offset:(s_offset - 1), end_offset:e_offset, message:locationMessage, result_kind:eType, result_file:file of mydoc, result_line:locationLine}
                   copy resultEntry to end of resultItems
               end if
               
           end repeat
           
           make new results browser with data resultItems with properties {name:"Compile Errors in " & sourceFileName}
       end tell
   end if
end main

Last edited by McUsrII (2014-02-20 05:55:16 pm)

Offline

 

#6 2014-02-20 04:31:55 pm

McUsrII
Member
Registered: 2012-11-21
Posts: 3046
Website

Re: Making a compile Script for BareBones Editor with Results browser.

Hello.

I just added some parenthesis around the do shell script  line  I use to "cat back" the error output from the compiler with.
I am not sure why I suddenly had to do that, but the fix works.

Offline

 

#7 2014-02-20 05:30:30 pm

McUsrII
Member
Registered: 2012-11-21
Posts: 3046
Website

Re: Making a compile Script for BareBones Editor with Results browser.

Hello.

I have harnessed the script slightly.

Last edited by McUsrII (2014-02-20 05:34:56 pm)

Offline

 

#8 2014-02-20 05:56:44 pm

McUsrII
Member
Registered: 2012-11-21
Posts: 3046
Website

Re: Making a compile Script for BareBones Editor with Results browser.

Hello.

I have hopefully removed the last bug, which was that I read an empty paragraph out of the sed filter, which caused the last compiler Error to be copied twice into the Result Browser.

Offline

 
  • Index
  •  » Code Exchange
  •  » Making a compile Script for BareBones Editor with Results browser.

Board footer

Powered by FluxBB

RSS (new topics) RSS (active topics)