Wednesday, May 27, 2009

Blogger source code syntax highlighting

If you've read my last few blog posts you might have noticed that my code snippets now have syntax highlighting that looks similar to Flex Builder.

I've found many people asking how to get syntax highlighting to work on source code that is pasted into Blogger. Most solutions use CSS and Javascript to accomplish that with varying levels of success. I've chosen to go a different route and am using a parser to turn ActionScript text into html which I then paste right into a blog post (under "Edit Html").

I'm using a slightly modified version of this amazing free parser called Java2Html created by Markus Gebhard (GNU License). It is a Java Swing application (or Applet) that takes in input text and outputs html which you can easily copy and paste into a blog. The original version (which I believe is last updated in 2006) has three different style options - Eclipse, Kawa, and Monochrome. I've added a fourth option FlexBuilder that uses the default syntax highlighting styles found in ActionScript.

If you want to try out my version, I've posted the applet here: java2html

Here are some of the options you can use (in the panel on the right side):
  • Style - choose one of the 4 code styles (use FlexBuilder for ActionScript)
  • Line numbers - shows line numbers in the html
  • Table border - draws a 2 pixel gray border around the code block
  • Background color - if checked then a white background color is set on the code block
  • Include <html> and <body> tags - if false then the output html doesn't inclde the <html> and <body> tags, only the content.
  • Use <br> at the end of lines - if false then the html won't contain <br> tags
  • Include new lines ("\n") - if false then the html won't contain new line characters. Turn this off if you want to paste your code into Blogger since it treats new lines as breaks!
  • CSS Class - by default the code block is wrapped inside a <div class="java"> tag. This option configures the class="java" part.

  • Again I can't take much credit for this. All I've really done is add a few of the options mentioned above and changed the parser slightly to work with ActionScript keywords (such as function, var, etc).

    Here is an example of a very simple code snippet with and without styling:
    private function get string():String {
    var str:String = "String";
    return str;
    }
    private function get string():String {
        var str:String = "String";
        return str;

                

    One more thing, I haven't tested the various Target options, I only use the default "XHTML 1.0 Transitional (inlined fonts)".

    Tuesday, May 26, 2009

    Sorting string characters alphabetically

    In Java if you want to sort the characters in a String alphabetically it is very easy:
    String test = "sorting";
    char[] chars = test.toCharArray();
    Arrays.sort(chars);
    System.out.println(new String(chars))// prints out "ginorst"

    But how can we do this in Flex/ActionScript? Perhaps there is an easier way than this, but here are my utility functions that sorts the characters in a String by putting each character into an array, sorting the array, then joining the array back into a String.
    /**
     * Converts the string's characters into an array.
     @param string the string to convert into an array
     @param unique if true then only unique characters are added to the array
     @param ignoreCase only applies if the unique property is set to true
     */
    public static function toCharArray(string:String, unique:Boolean = false
           ignoreCase:Boolean = false):Array {
        var array:Array = new Array();
        if ((string != null&& (string.length > 0)) {
            // for tracking unique letters
            var seen:Object = new Object();
            // add each character to the array
            for (var i:int = 0; i < string.length; i++) {
                var char:String = string.charAt(i);
                if (unique) {
                    // unique characters only, possibly ignoring case 
                    // use the character code as the key (could just use the letter too) 
                    var key:String = (ignoreCase ? char.toUpperCase() : char);
                    key = key.charCodeAt(0).toString(10);
                    if (!seen.hasOwnProperty(key)) {
                        seen[keytrue;
                        array.push(char);
                    }
                else {
                    array.push(char);
                }
            }
        }
        return array;
    }

    /**
     * Sorts the characters in the string alphabetically. 
     @param ignoreCase if false (default) upper case letters come first then lowercase
     @param descending if true then the String is sorted in reverse
     @param unique if true then only unique characters are sorted and returned
     */
    public static function sort(string:String, ignoreCase:Boolean = false
                descending:Boolean = false, unique:Boolean = false):String {
        // no point in sorting
        if ((string == null|| (string.length <= 1)) {
            return string;
        }
        var chars:Array = toCharArray(string, unique, ignoreCase);
        var options:uint = 0;
        if (ignoreCase) {
            options = options | Array.CASEINSENSITIVE;
        }
        if (descending) {
            options = options | Array.DESCENDING;
        }
        chars.sort(function(s1:String, s2:String):int {
            return ObjectUtil.stringCompare(s1, s2, ignoreCase);
        }, options);
        
        var sorted:String = chars.join("");
        return sorted;
    }

    Feel free to comment if you know of a simpler way to sort characters in a String.

    Wednesday, May 20, 2009

    Using Flex and AMFPHP without a services-config.xml file

    I've been working a bit with amfphp, sending data between Flex and PHP using the RemoteObject class. Initially I put the generic services-config.xml file in my application's src directory:
    <services-config>
    <services>
    <service id="amfphp-flashremoting-service"
    class="flex.messaging.services.RemotingService"
    messageTypes="flex.messaging.messages.RemotingMessage">
    <destination id="amfphp">
    <channels>
    <channel ref="my-amfphp"/>
    </channels>
    <properties>
    <source>*</source>
    </properties>
    </destination>
    </service>
    </services>
    <channels>
    <channel-definition id="my-amfphp" class="mx.messaging.channels.AMFChannel">
    <endpoint uri="http://localhost/amfphp/gateway.php"
    class="flex.messaging.endpoints.AMFEndpoint"/>
    </channel-definition>
    </channels>
    </services-config>
    And changed my project properties to add this line to the Flex Compiler page:
    -services services-config.xml

    But I just came across this post which shows how to get around having to have an XML file by defining the channel at runtime.

    So here is my simplified Flex code:
    import mx.rpc.events.ResultEvent;
    import mx.rpc.events.FaultEvent;
    import mx.rpc.remoting.RemoteObject;
    import mx.messaging.ChannelSet;
    import mx.messaging.channels.AMFChannel;


    var url:String = "http://localhost/amfphp/gateway.php";
    var channel:AMFChannel = new AMFChannel("my-amfphp", url);
    var channelSet:ChannelSet = new ChannelSet();
    channelSet.addChannel(channel);
    var ro:RemoteObject = new RemoteObject("amfphp");
    ro.channelSet = channelSet;
    // Specify the PHP class
    ro.source = "TestService";
    ro.addEventListener(FaultEvent.FAULT, function(event:FaultEvent):void {
        trace("Fault: " + event.fault);
    });
    ro.addEventListener(ResultEvent.RESULT, function(event:ResultEvent):void {
        trace("Result: " + event.result);
    });
    // the TestService class must have a public helloWorld function
    ro.helloWorld();

    You could also do the same in MXML:
    <mx:ChannelSet id="channelSet">
    <mx:channels>
    <mx:AMFChannel uri="http://localhost/amfphp/gateway.php"/>
    </mx:channels>
    </mx:ChannelSet>
    <mx:RemoteObject source="TestService" destination="amfphp"
    channelSet="{channelSet}" id="remoteObject"
    fault="trace('Fault: '+event.fault)"
    result="trace('Result: '+event.result)"/>

    And the corresponding PHP code (put the php file inside your webroot/amfphp/services directory):
    <?php
    class TestService {
        public function helloWorld() {
            return "Hello from PHP";
        }
    }
    ?>

    So what are the benefits of this approach? Well, I'm not sure. In my case it was better because I have one logging class that does all the remoting, and is used by many different Flex applications. So instead of having to duplicate the services-config.xml file in every flex application this way I could define my endpoint url (http://localhost/amfphp/gateway.php) in one place.

    Here is another site that is useful when getting started with amfphp:
  • amfphp video tutorials