AAML: The Simplest Markup Language for Android

Published on April 03, 2013

AAML: The Simplest Markup Language for Android

    You may find this stupid, but I do not like the IDE. Usually I do all the work in vim + tmux + terminal. I recognize all the advantages of the IDE, it’s just more convenient for me in a good text editor. But this is not about that.

    When I write something for android, I often edit XML (markup, styles, lines, ...). So in a text editor, this is not very convenient. And I decided to spend a couple of hours and write an XML generator based on a simplified markup language (such as lesscss or stylus for CSS). Still, NIH is a very seductive stimulus.

    The AAML language (another android markup language) turned out with a very simple syntax. Elements begin with a colon. Commas (or line breaks) separate attributes. Tabs (or spaces, or both) determine the nesting of elements. Comments begin with a pound. Some simple layout looks like this:

    # Main layout
    :LinearLayout layout fill, padding 0dp 16dp, orientation vertical
            :EditText
                    layout fill wrap
                    hint @string/to
            :EditText
                    layout fill wrap
                    hint @string/subject
            :EditText
                    layout fill 0dp 1
                    gravity top
                    hint @string/message
            :Button#btn_send
                    layout 100dp wrap
                    gravity right
                    text @string/send
    

    Such AAML markup compiles into:

    <?xml version="1.0" encoding="utf-8"?>
    <!-- Main layout -->
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    	android:layout_width="fill_parent"
    	android:layout_height="fill_parent"
    	android:paddingTop="0dp"
    	android:paddingRight="16dp"
    	android:paddingBottom="0dp"
    	android:paddingLeft="16dp"
    	android:orientation="vertical">
    	<EditText
    		android:layout_width="fill_parent"
    		android:layout_height="match_parent"
    		android:hint="@string/to" />
    	<EditText
    		android:layout_width="fill_parent"
    		android:layout_height="match_parent"
    		android:hint="@string/subject" />
    	<EditText
    		android:layout_width="fill_parent"
    		android:layout_height="0dp"
    		android:layout_weight="1"
    		android:gravity="top"
    		android:hint="@string/message" />
    	<Button
    		android:id="@+id/btn_send"
    		android:layout_width="100dp"
    		android:layout_height="match_parent"
    		android:gravity="right"
    		android:text="@string/send" />
    </LinearLayout>
    

    The DRY principle also supports macros and aliases. Aliases allow you to set a new name for something - an attribute (to write “wrap” instead of “wrap_content”), a value (to determine the color or size of the font once and use the alias as the name of the variable), etc.

    Macros take a number of arguments. True, names cannot be given to arguments (and macros are supposed to be only the simplest). Instead, positional arguments are used, as in Bash ($ 1, $ 2, $ 3, etc.). Here are the macros and aliases used in the example above:

    # Алиасы
    :def wrap wrap_content
    :def fill match_parent
    :def match match_parent
    # Макросы
    :def layout:3 layout_widht $1, layout_height $2, layout_weight $3
    :def layout:2 layout_widht $1, layout_height $2
    :def layout:1 layout $1 $1
    :def padding:4 paddingTop $1, paddingRight $2, paddingBottom $3, paddingLeft $4
    :def padding:2 padding $1 $2 $1 $2
    :def padding:1 padding $1 $1
    

    Probably, such macros should be made standard for different types of XML (for layout - one, for strings - others, etc.)

    AAML is written in python. It has no dependencies, there are only 200 lines of code there. It works in two modes - it converts a * .aaml file to * .xml or recursively processes all files from one folder and puts the resulting xml into another. This is convenient if you create aaml / layout, aaml / values, aaml / xml and add the results to res / layout, etc.

    To automate this process, you can create custom_rules.xml:

    <?xml version="1.0" encoding="UTF-8"?>
    <project>
        <target name="-pre-build">
            <exec executable="aaml">
                <arg value="aaml"/>
                <arg value="res"/>
            </exec>
        </target>
    </project>
    

    Now aaml will be converted to xml every time you build the project automatically.

    Sources are located at bitbucket: bitbucket.org/zserge/aaml
    License - MIT.

    At the end of the post I have a question for the Khabrovsk residents - is it worth developing this project? Are there any other freaks that write XML manually? If so, then any suggestions, feature requests, comments, bugs, criticism are welcome.