I primarily write this post as a reminder of all the search I go through in order to optimize my daily work with ActionScript (and some other languages) in Gedit.

There's not plenty of examples through the web on how to develop actionscript under Gedit, below are the few ones that are relevant :

  • This post or this post provides a *.lang file to add the syntax colouring for ActionScript.
  • This post show how to compile a file using the External Tools plug-in as I'll do myself later in this post.
  • And there's this plug-in listed in the Gedit2 list of third-party plug-ins, Automatic compilation for SWFTools, which says: Automatically call swfc compilation for saved file, if it has ".swfc" extension. But that's not what I am looking for.

Color syntax

First I really wasn't satisfied with the current syntax colouring files available on the web. ActionScript is quite verbose sometimes and it's good to have a proper way to visually recognize each elements. So I recreated my own language file based on the javascript one.

This one supports :

  • Typing (var, arguments, returns)
  • E4X (both declarations and access)
  • RegExp
  • Metadata
  • ASDoc comments
  • Conditional Compilation

The only case I wasn't able to fix yet is the ternary operator a ? b : c where c appear as a type.

You can find the language file in the attached files of this post or by clicking this link. You have to put this file in your ~/.local/share/gtksourceview2/language-specs/ directory.

Of course if you find some cases which are not covered by this file, don't hesitate to notice me in the comments.

External Tools setup

Add actionscript support in the External Tools links parser

To allow the output panel of the External Tools plug-in to detect error paths in the mxmlc output and provide the ad-hoc links, open the following file in your favourite text editor :

sudo gedit /usr/lib/gedit-2/plugins/externaltools/linkparsing.py

Then add this declaration at the end of the file :

# as3 'Test.as(8): col: 28'
REGEXP_AS3 = r"""
^(?P<lnk>
    (?P<pth> .*\.[aA][sS] )
    \(
    (?P<ln> \d+ )\)
)\:\s
"""

And finally add a self.add_regexp(REGEXP_AS3) in the init method of the LinkParser class.

That's it.

Advanced compilation script

This part is a bit harder. It use the same technique as This post on Experimentalized but with a more complex setup. This setup is designed to allow to compile both files that are in a structured project and files that are not.

The thing is, I prefer having all my main classes (the files to compile) at the root of a src folder in my project folder, then having a bin and a build directory at the same level. And still, there's always some times when I need to quickly test something without bothering about if the file is within a project or not, and where it is in the project.

Each build I need to setup will be stored in the build folder. Each including a common configuration file with some predefined setup such as common dependencies and differentiated options sets for release and debug builds. This way, all the compiled file in the project share the same settings.

The script will first check for the existence of the various folders and files, if they don't exist they're created. And then the build file is launched. The cool thing is when you have generated the build file the first time, you can modify it and it will be executed each time you launch the script. It allow you to have a really minimal setup which can works for all files, and, without losing the advantage of having a compilation command on a key short-cut, changing completely the setup of your build (with generation of the locale files or application signing in case of an AIR application).

Here what the tool file looks like :

#!/bin/sh
dir=$GEDIT_CURRENT_DOCUMENT_DIR
file=$GEDIT_CURRENT_DOCUMENT_NAME
file_base=${file%as}
ext='swf'
build_ext='build.sh'
report_ext='xml'

# avoid to process on something else that *.as files
if [ ${file%.*} != ".as" ]
then
	echo "Can't proceed on file $file, it must be an actionscript file"
	return
fi

# cut the path just before a src dir
src=${dir%/src*}

# test wether the file is in src or not
if [ $dir = $src ]
then 
	project_dir=${dir%/*}
	is_part_of_the_src_tree=0
	src_dir=$dir
	echo "$file is not in a src tree"
else
	project_dir=$src
	is_part_of_the_src_tree=1
	src_dir=$project_dir/src
	echo "$file is in a src tree"
fi

# setup other dir paths
build_dir=$project_dir/build
bin_dir=$project_dir/bin
reports_dir=$project_dir/reports

# test for existence of a bin, reports and build dir in the parent folder
if [ -e $build_dir ]
then
	build_dir_exist=1
else
	build_dir_exist=0
fi

if [ -e $bin_dir ]
then
	bin_dir_exist=1
else
	bin_dir_exist=0
fi

if [ -e $reports_dir ]
then
	reports_dir_exist=1
else
	reports_dir_exist=0
fi

# test whether we need to create bin and build folders
if [ $is_part_of_the_src_tree -eq 1 ]
then
	if [ $bin_dir_exist -eq 0 ]
	then 
		mkdir $bin_dir
		echo "$bin_dir din't exist and was created"
	fi
	
	if [ $build_dir_exist -eq 0 ]
	then 
		mkdir $build_dir
		echo "$build_dir din't exist and was created"
	fi
	
	if [ $reports_dir_exist -eq 0 ]
	then 
		mkdir $reports_dir
		echo "$reports_dir din't exist and was created"
	fi
	
	build=$build_dir/$file_base${build_ext}
	report=$reports_dir/$file_base${report_ext}
	build_commons=$build_dir/build-commons.sh
	output=$bin_dir/$file_base${ext}

elif [ $bin_dir_exist -eq 1 -o $build_dir_exist -eq 1 ]
then
	echo "$file is not in the src tree, but a build or a bin folder exist in the parent folder."
  if [ $bin_dir_exist -eq 0 ]
	then 
		mkdir $bin_dir
		echo "$bin_dir din't exist and was created."
	fi
	
	if [ $build_dir_exist -eq 0 ]
	then 
		mkdir $build_dir
		echo "$build_dir din't exist and was created"
	fi
	
	if [ $reports_dir_exist -eq 0 ]
	then 
		mkdir $reports_dir
		echo "$reports_dir din't exist and was created"
	fi
	
	build=$build_dir/$file_base${build_ext}
	report=$reports_dir/$file_base${report_ext}
	build_commons=$build_dir/build-commons.sh
	output=$bin_dir/$file_base${ext}
	
else
	echo "Builds for $file will be created in the same directory."
	report=$dir/$file_base${report_ext}
	build=$dir/$file_base${build_ext}
	build_commons=$dir/build-commons.sh
	output=$dir/$file_base${ext}

fi

# test whether the builds file exist or not, and then create it if they don't
if [ ! -e $build_commons ] 
then
	echo "
flex4=PATH/TO/YOUR/SDK\n\
mxmlc=\$flex4/bin/mxmlc\n\

\n\
# Here you can modify the default setups availables in your build files
# hint : use 4 backslash in the generator to display 1 in the generated ;)
default_options=\"-source-path+=$src_dir\" \n\
\n\
defaults_debug=\"-debug=true \$default_options\" \n\
\n\
defaults_release=\"\$default_options\" \n\ " > $build_commons
	echo "$build_commons didn't exist and was created"
fi

if [ ! -e $build ] 
then
	echo "#!/bin/sh \n\
. $build_commons \n\
\n\
echo 'Start compilation'\n\
\$mxmlc \$defaults_debug \\\\\n    -output $output \\\\\n    -link-report $report \\\\\n    -- $dir/$file \n\
\n\
gnome-open $dir/$file" > $build
	echo "$build didn't exist and was created"
fi

sh $build

You just have to create a new tools in the External Tools plug-in configuration dialog and paste the code above inside and then assigning it to the shortcut of your choice.

What does this script do ?
  1. We verify that the file to compile is part of a src folder, either at its root or in one of its sub-folders. The test is done by splitting the string before src, if the two strings are equals, the split failed and their is no src in the path.
  2. Then we check for the bin, build and reports folders in the parent directory of the current file directory. If they exists, even if the file isn't in the src tree, the build files will be created in that place. It allow you to compile files that exists in a folder in your project root. An examples folder for instance. If they don't exists, we will place the build and output files in the same folder than the compiled file.
  3. We can now check for the build files existence and create it if they don't.
  4. Finally we execute the main build file as we have made sure that it exist in the right place. And after the compilation, we open the file using the gnome-open command (For that, I recommend you to download a standalone debug version of the Flash Player and make the association within a Nautilus window).

You can notice that I automatically generates a report for each compilation using the -link-report option of mxmlc. I use the generated report as the source for the localisation generation. This is explain later in this post.

Other plug-ins that are pretty useful

Native
  • Snippets to easily create templates.
  • FileBrowser.
  • Sort to order the import mess from time to time.
From the gedit-plugins package

This package can be installed with :

sudo apt-get install gedit-plugins
  • Code Completion which complete with the words in all the active documents.
  • Bracket Completion.
  • Code Comment.
  • Color Picker.
  • Terminal.
  • Session Saver.
Third party
  • Line Tools which add support for delete/duplicate and move up or down lines.
  • Symbol Browser which use CTags to parse code and provide a raw outline of the file content.
  • File Search which allow to search a string in a set of files, and display the results with direct links in a tab in the bottom panel, really useful for refactoring ;).
  • Regex Search & Replace.
  • Right Pane because with all this plug-in you will need extra space to avoid to switch from panel tabs all the time.
  • Split View 3 to split a document view in two with the same or a different document in each part.

Symbol Browser setup

First things first, the Symbol Plugin require the exuberant-ctags package which can be installed with.

sudo apt-get install exuberant-ctags

This is what I can see in my Symbol Browser panel with the file in the previous screenshot.

To get the same results you can just download the ctags and the symbols.zip files at the end of this post. The former must be renamed to .ctags and placed in your home directory, the latter must be unzipped and then placed in the ~/.gnome2/gedit/ directory.

The CTags file also contains definitions for CSS, SCSS (Sassy CSS) and PixelBender Kernel files.

Other useful scripts

Localisation file generation

I use gettext to handle localisation. Based on the excellent post of Alessandro Crugnola and its actionscript3gettext lib.

To install the gettext utilities use the following command :

sudo apt-get install gettext

The process of generating the localisation is in 3 steps :

  1. Generates a *.fil file with all the source files to feed the xgettext utility.
  2. Generates a *.pot file with the xgettext utility.
  3. Generates the *.mo file which will contains the localisations to load in your application.

For the first step I use a small script I made myself and which can be found here. I simply create a symbolic link named asgettext in my ~/bin folder to use it freely from my Gedit script. The asgettext.py script takes a *.xml report file and generates the *.fil file with the path to all the source files compiled in the *.swf.

Then, here the Gedit script :

#!/bin/sh
dir=$GEDIT_CURRENT_DOCUMENT_DIR
file=$GEDIT_CURRENT_DOCUMENT_NAME
file_base=${file%as}
report_ext='xml'
fil_ext='fil'
pot_ext='pot'

# cut the path just before a src dir
src=${dir%/src*}

# test wether the file is in src or not
if [ $dir = $src ]
then 
	project_dir=${dir%/*}
	is_part_of_the_src_tree=0
	echo "$file is not in a src tree"
else
	project_dir=$src
	is_part_of_the_src_tree=1
	echo "$file is in a src tree"
fi

# setup other dir paths
locales_dir=$project_dir/bin/locales
reports_dir=$project_dir/reports

# test for existence of a report for this file dir in the project folder 
if [ -e $reports_dir ]
then
	reports_dir_exist=1
	report=$reports_dir/$file_base${report_ext}
else
	reports_dir_exist=0
	report=$dir/$file_base${report_ext}
fi

# if the file can't be found we exit
if [ ! -e $report ]
then
	echo "Can't find any report file for $file"
	echo "Exit"
	exit
fi

if [ -e $locales_dir ]
then
	locales_dir_exist=1
else
	locales_dir_exist=0
fi

# test whether we need to create the locales folders
if [ $is_part_of_the_src_tree -eq 1 ]
then
	if [ $locales_dir_exist -eq 0 ]
	then 
		mkdir $locales_dir
		echo "$locales_dir din't exist and was created"
	fi
		
	fil=$locales_dir/$file_base${fil_ext}
	locale=$locales_dir/$file_base${pot_ext}

elif [ $locales_dir_exist -eq 1 ]
then
	echo "$file is not in the src tree, but a locales dir exist in the parent folder."
	
	fil=$locales_dir/$file_base${fil_ext}
	locale=$locales_dir/$file_base${pot_ext}
	
else
	echo "Locales for $file will be created in the same directory."
	fil=$dir/$file_base${fil_ext}
	locale=$dir/$file_base${pot_ext}
fi

asgettext -o $fil -d $report
xgettext --from-code=UTF-8 -o $locale -L Python -f $fil

This script use the same structure rules as the previous one. It will check for the existence of a *.xml file for the current file either in the reports folder or in the source file's folder itself. If the reports folder have been found, a locales folder is created in the bin dir (if it don't exist yet), else the locales files will be created in the same folder as the current file. Then, all the path are created and both asgettext and xgettext are called with their corresponding arguments.

Finally to generates the *.mo files, you'll need to use whatever *.pot editor, such as PoEdit :

sudo apt-get install poedit
Pixel Bender Kernel compilation

If you use (or want to use) Pixel Bender in Gedit, below a script that compile a *.pbk file to a *.pbj file with the same name in the same folder.

If you don't know how to use Pixel Bender under linux, you can read my previous post Using PixelBender on Linux with Wine and PBDT.

For this script, I previously created a symbolic link to my pbutil file in my ~/bin directory.

#!/bin/sh
DIR=$GEDIT_CURRENT_DOCUMENT_DIR
FILE=$GEDIT_CURRENT_DOCUMENT_NAME
EXT='pbj'
PBJ=${FILE%pbk}${EXT}

if [ ${file%.*} != ".pbk" ]
then
	echo "Can't proceed on file $file, it must be a Pixel Bender Kernel file"
	return
fi

pbutil $DIR/$FILE $DIR/$PBJ

That's all for today. I have some other scripts under the hand but they're not actionscript related, so see you next time.

Edit 15/06/2011 I improved the scripts by testing the extension before doing anything, which was not done before.