Index: Commands/Compile.tmCommand
===================================================================
--- Commands/Compile.tmCommand	(revision 0)
+++ Commands/Compile.tmCommand	(revision 0)
@@ -0,0 +1,72 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>beforeRunningCommand</key>
+	<string>saveActiveFile</string>
+	<key>command</key>
+	<string>#!/usr/bin/env ruby
+require 'date'
+require ENV['TM_SUPPORT_PATH'] + "/lib/exit_codes.rb"
+if ENV['TM_ERLANG_COMPILE'] == 'disable'
+  TextMate.exit_discard
+end
+
+projectDir = ENV['TM_PROJECT_DIRECTORY']
+fileDir = ENV['TM_DIRECTORY']
+erlangHome = ENV['ERLANG_HOME']
+rsrcPath = ENV['TM_BUNDLE_PATH'] + '/Resources'
+
+output = `cd #{projectDir};make --silent 2&gt;/dev/null`
+if output.length() != 0
+	puts "
+&lt;html&gt;
+	&lt;head&gt;
+		&lt;title&gt;Erlang Build: #{projectDir}&lt;/title&gt;
+	&lt;/head&gt;
+	&lt;style&gt;
+	ul {
+		padding-left: 20px
+	}
+	li.error {
+		list-style-image: url('#{rsrcPath}/tr_warn_error.jpg')
+	}
+	li.warning {
+		list-style-image: url('#{rsrcPath}/tr_warn_alert.jpg')
+	}
+	&lt;/style&gt;
+	&lt;body&gt;
+		&lt;h1&gt;Build errors/warnings as of #{DateTime.now()}&lt;/h1&gt;
+		&lt;ul&gt;"
+	output.each_line{|line|
+		if /(.*):(\d+):(\sWarning:|)\s(.*)/ =~ line
+			file = fileDir + '/' + Regexp.last_match[1]
+			lineNum = Regexp.last_match[2]
+			className = Regexp.last_match[3].size == 0 ? 'error' : 'warning'
+			message = Regexp.last_match[4]
+			url = "txmt://open/?url=file://" +
+			    file.gsub(/[^a-zA-Z0-9.-\/]/) { |m| sprintf("%%%02X", m[0]) } +
+		    	    "&amp;amp;line=" + lineNum
+			puts "&lt;li class=\"#{className}\"&gt;&lt;a href=\"#{url}\"&gt;#{line}&lt;/a&gt;"
+		end
+	}
+	puts "
+		&lt;/ul&gt;
+	&lt;/body&gt;
+&lt;/html&gt;"
+	TextMate.exit_show_html
+end</string>
+	<key>input</key>
+	<string>none</string>
+	<key>keyEquivalent</key>
+	<string>@s</string>
+	<key>name</key>
+	<string>Compile</string>
+	<key>output</key>
+	<string>discard</string>
+	<key>scope</key>
+	<string>source.erlang</string>
+	<key>uuid</key>
+	<string>B8CF3426-DC7E-4A60-A15B-1C4B08E59FF4</string>
+</dict>
+</plist>
Index: Commands/Completion.tmCommand
===================================================================
--- Commands/Completion.tmCommand	(revision 0)
+++ Commands/Completion.tmCommand	(revision 0)
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>beforeRunningCommand</key>
+	<string>nop</string>
+	<key>command</key>
+	<string>#!/usr/bin/env python
+import socket
+import sys
+import os
+import subprocess
+s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+try:
+    s.connect(('127.0.0.1',2345))
+    tm_line_number = int(os.environ['TM_LINE_NUMBER'])
+    tm_line_index = int(os.environ['TM_LINE_INDEX'])
+    module = os.environ['TM_FILEPATH'].split('/').pop().split('.').pop(0)
+    paths = '"%s/%s"' % (os.environ['TM_PROJECT_DIRECTORY'], os.environ['TM_ERLANG_BIN'])
+    s.send('{%(module)s,[%(paths)s]}.' % locals())
+    s.send(os.linesep)
+    line_num = 1
+    for line in sys.stdin:
+        if line_num == tm_line_number:
+            s.send(line[0:tm_line_index].rstrip() + os.linesep)
+            break
+        line_num = line_num + 1
+    s.send('\f' + os.linesep)
+    sys.stdout.write(s.recv(4096).rstrip())
+    sys.stdout.flush()
+except socket.error:
+    support = os.environ['TM_BUNDLE_SUPPORT']
+    os.system('cd "%(support)s"/completion; make --silent &gt; /dev/null 2&gt;&amp;1' % locals())
+    os.system('erl -noshell -detached -pa "%(support)s/completion/ebin" -s tm_complete_server' % locals())</string>
+	<key>input</key>
+	<string>document</string>
+	<key>keyEquivalent</key>
+	<string>~</string>
+	<key>name</key>
+	<string>Completion</string>
+	<key>output</key>
+	<string>insertAsSnippet</string>
+	<key>scope</key>
+	<string>source.erlang</string>
+	<key>uuid</key>
+	<string>B6139782-669C-4E78-8B53-B70EC16A4044</string>
+</dict>
+</plist>
Index: Commands/Documentation for Word : Selection (man).tmCommand
===================================================================
--- Commands/Documentation for Word : Selection (man).tmCommand	(revision 0)
+++ Commands/Documentation for Word : Selection (man).tmCommand	(revision 0)
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>beforeRunningCommand</key>
+	<string>nop</string>
+	<key>command</key>
+	<string>export MANPATH=$ERLANG_HOME/man
+word=${TM_SELECTED_TEXT:-$TM_CURRENT_WORD}
+
+try_man () {
+	if man -w "$word" &amp;&gt;/dev/null; then
+		page=$("$TM_SUPPORT_PATH/bin/html_man.sh" -a "$word")
+		echo "&lt;meta http-equiv='Refresh' content='0;URL=tm-file://$page'&gt;"
+		exit_show_html
+	fi
+}
+
+MANSECT=${MANSECT:-2:3:4:5:6:7:8:9} try_man
+try_man
+
+echo "Couldn’t find documentation for “${word}”"
+</string>
+	<key>dontFollowNewOutput</key>
+	<true/>
+	<key>fallbackInput</key>
+	<string>word</string>
+	<key>input</key>
+	<string>selection</string>
+	<key>keyEquivalent</key>
+	<string>^h</string>
+	<key>name</key>
+	<string>Documentation for Word / Selection (man)</string>
+	<key>output</key>
+	<string>showAsTooltip</string>
+	<key>scope</key>
+	<string>source.erlang</string>
+	<key>uuid</key>
+	<string>81314DDD-FC3A-4497-938F-9AD2079A5C6E</string>
+</dict>
+</plist>
Index: Commands/Open EShell.tmCommand
===================================================================
--- Commands/Open EShell.tmCommand	(revision 0)
+++ Commands/Open EShell.tmCommand	(revision 0)
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>beforeRunningCommand</key>
+	<string>nop</string>
+	<key>command</key>
+	<string>osascript &lt;&lt;-APPLESCRIPT
+	tell application "Terminal"
+     	activate
+     	do script "erl -pa ${TM_PROJECT_DIRECTORY}/${TM_ERLANG_BIN}"
+	end tell
+APPLESCRIPT</string>
+	<key>input</key>
+	<string>none</string>
+	<key>keyEquivalent</key>
+	<string>^O</string>
+	<key>name</key>
+	<string>Open EShell</string>
+	<key>output</key>
+	<string>discard</string>
+	<key>scope</key>
+	<string>source.erlang</string>
+	<key>uuid</key>
+	<string>45758473-E776-4D63-A16A-1C87A3660DCF</string>
+</dict>
+</plist>
Index: info.plist
===================================================================
--- info.plist	(revision 9339)
+++ info.plist	(working copy)
@@ -63,6 +63,7 @@
 	<string>Erlang</string>
 	<key>ordering</key>
 	<array>
+		<string>B8CF3426-DC7E-4A60-A15B-1C4B08E59FF4</string>
 		<string>58EA597D-5158-4BF7-9FB2-B05135D1E166</string>
 		<string>3FBFF015-B650-4734-848C-47B53ACD5E32</string>
 		<string>AE84FFDF-2D5A-4331-A301-6CF34CF26CD8</string>
@@ -100,6 +101,9 @@
 		<string>756D50E8-C3E9-4ACD-B246-031E4D91D807</string>
 		<string>15DF3174-A8CD-40DA-BE74-B991425BA9EB</string>
 		<string>AF80483E-996B-44E8-A76D-8CD7AA3CDB8B</string>
+		<string>B6139782-669C-4E78-8B53-B70EC16A4044</string>
+		<string>81314DDD-FC3A-4497-938F-9AD2079A5C6E</string>
+		<string>45758473-E776-4D63-A16A-1C87A3660DCF</string>
 	</array>
 	<key>uuid</key>
 	<string>065A8821-DD83-4753-90E3-AA70EC12E150</string>
Index: Resources/tr_warn_alert.jpg
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream

Property changes on: Resources/tr_warn_alert.jpg
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Index: Resources/tr_warn_error.jpg
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream

Property changes on: Resources/tr_warn_error.jpg
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Index: Support/completion/src/tm_complete_server.erl
===================================================================
--- Support/completion/src/tm_complete_server.erl	(revision 0)
+++ Support/completion/src/tm_complete_server.erl	(revision 0)
@@ -0,0 +1,41 @@
+-module (tm_complete_server).
+-export([start/0]).
+
+start() -> spawn(fun run/0).
+
+run() ->
+    {ok, Listen} = gen_tcp:listen(2345, [list, {packet, line},
+                                         {reuseaddr, true},
+                                         {active, true}]),
+    spawn(fun() -> par_connect(Listen) end),
+    receive die -> ok end.
+
+par_connect(Listen) ->
+    {ok, Socket} = gen_tcp:accept(Listen),
+    spawn(fun() -> par_connect(Listen) end),
+    complete(Socket).
+
+complete(Socket) ->
+    receive
+        {tcp, Socket, Header} ->
+            {ok, {Module, Paths}} = term(Header),
+            [code:add_path(Path) || Path <- Paths],
+            Completion = tm_complete:string(Module, string(Socket)),
+            gen_tcp:send(Socket, Completion);
+        _ -> ok
+    end.
+
+term(String) ->
+    {ok, Tokens, _} = erl_scan:string(String),
+    erl_parse:parse_term(Tokens).
+
+string(Socket) -> lists:flatten(gather(Socket)).
+gather(Socket) ->
+    receive
+        {tcp, Socket, [$\f|_]} -> [];
+        {tcp, Socket, [$-|_]} -> gather(Socket);
+        {tcp, Socket, Data} ->
+            {ok, Cleaned, _} = regexp:gsub(Data, "[\r\n]", ""),
+            [Cleaned|gather(Socket)];
+        _ -> []
+    end.
Index: Support/completion/src/tm_menu.erl
===================================================================
--- Support/completion/src/tm_menu.erl	(revision 0)
+++ Support/completion/src/tm_menu.erl	(revision 0)
@@ -0,0 +1,16 @@
+-module(tm_menu).
+-export([selection/1]).
+-include_lib("xmerl/include/xmerl.hrl").
+
+selection([]) -> "";
+selection(MenuItems) ->
+    %% TODO: need better way to get path for tm_dialog
+    PlistXml = os:cmd(io_lib:format("/Applications/TextMate.app/Contents/PlugIns/Dialog.tmplugin/Contents/Resources/tm_dialog -u -p \"~s\"", [ascii_plist(MenuItems)])),
+    {PlistDoc, _Rest} = xmerl_scan:string(PlistXml),
+    selected( xmerl_xpath:string("/plist/dict/dict[preceding-sibling::key[1]='selectedMenuItem']/string[preceding-sibling::key[1]='title']/text()", PlistDoc)).
+
+selected([#xmlText{value=Selected}]) -> Selected;
+selected([]) ->"".
+
+ascii_plist(MenuItems) ->
+    ["{menuItems = (", [io_lib:format("{title = ~s;},", [Item]) || Item <- MenuItems], ");}"].
Index: Support/completion/src/complete.erl
===================================================================
--- Support/completion/src/complete.erl	(revision 0)
+++ Support/completion/src/complete.erl	(revision 0)
@@ -0,0 +1,101 @@
+-module (complete).
+-author('alain.odea@gmail.com').
+-license('http://opensource.org/licenses/afl-3.0.php').
+-export ([string/1, string/2]).
+
+string(String) -> string([], String).
+string(Local, String) ->
+    {ok, Tokens, 1} = erl_scan:string(String),
+    complete(Local, lists:reverse(Tokens)).
+
+complete(_, [{atom,1,Function},{':',1},{atom,1,Module},{'fun',1}|_]) ->
+    % select functions in fun M:F/Arity expression
+    Prefix = atom_to_list(Function),
+    {string:len(Prefix),[{fun_ref, F} || F <- lists:filter(starts_with(Prefix), Module:module_info(exports))]};
+complete(_, [{':',1},{atom,1,Module},{'fun',1}|_]) ->
+    % all functions in fun M:F/Arity expression
+    {0,[{fun_ref, F} || F <- Module:module_info(exports)]};
+complete([], [{atom,1,FunctionOrModule},{'fun',1}|_]) ->
+    % select modules in fun M:F/Arity expression
+    Prefix = atom_to_list(FunctionOrModule),
+    {string:len(Prefix), [{fun_ref, F} || F <- lists:filter(starts_with(Prefix), builtins())] ++
+    [{module, M} || M <- lists:filter(starts_with(Prefix), lists:sort(erlang:loaded()))]};
+complete(Local, [{atom,1,FunctionOrModule},{'fun',1}|_]) ->
+    % select local functions in fun F/Arity expression
+    % select modules in fun M:F/Arity expression
+    Prefix = atom_to_list(FunctionOrModule),
+    {string:len(Prefix), [{fun_ref, F} || F <- lists:filter(starts_with(Prefix), Local:module_info(exports) ++ builtins())] ++
+    [{module, M} || M <- lists:filter(starts_with(Prefix), lists:sort(erlang:loaded()))]};
+complete([], [{'fun',1}|_]) ->
+    % select modules in fun M:F/Arity expression
+    {0, [{fun_ref, F} || F <- builtins()] ++
+    [{module, M} || M <- lists:sort(erlang:loaded())]};
+complete(Local, [{'fun',1}|_]) ->
+    % select functions in fun F/Arity expression OR
+    % select modules in fun M:F/Arity expression
+    {0, [{fun_ref, F} || F <- Local:module_info(exports)] ++
+    [{module, M} || M <- lists:sort(erlang:loaded())]};
+
+complete(_, [{':',1},{atom,1,Module}|_]) ->
+    % all functions in M:F expression
+    {0, [{call, F} || F <- Module:module_info(exports)]};
+complete(_, [{atom,1,Function},{':',1},{atom,1,Module}|_]) ->
+    % select functions in M:F expression
+    Prefix = atom_to_list(Function),
+    {string:len(Prefix), [{call, F} || F <- lists:filter(starts_with(Prefix), Module:module_info(exports))]};
+
+complete(_, [{'(',1},{atom,1,spawn}|_]) ->
+    % all modules in spawn(M,F,A) expression
+    % should complete to spawn(M,
+    % TODO: support spawn(Node, M, F, A) as well
+    {0, [{module, M} || M <- lists:sort(erlang:loaded())]};
+complete(_, [{atom,1,Module},{'(',1},{atom,1,spawn}|_]) ->
+    % select modules in spawn(M,F,A) expression
+    Prefix = atom_to_list(Module),
+    {string:len(Prefix), [{module, M} || M <- lists:filter(starts_with(Prefix), lists:sort(erlang:loaded()))]};
+complete(_, [{',',1},{atom,1,Module},{'(',1},{atom,1,spawn}|_]) ->
+    % all functions in spawn(M,F,A) expression
+    % should complete to spawn(M, F,[${0:arg1},${1:arg2},...])
+    {0, [{function, F} || F <- Module:module_info(exports)]};
+complete(_, [{atom,1,Function},{',',1},{atom,1,Module},{'(',1},{atom,1,spawn}|_]) -> %
+    % select functions in spawn(M,F,A) expression
+    Prefix = atom_to_list(Function),
+    {string:len(Prefix), [{function, F} || F <- lists:filter(starts_with(Prefix), Module:module_info(exports))]};
+
+complete(_, [{atom,1,is},{'when',1}|_]) ->
+    % all standard guard expressions
+    % TODO: support all allowable guard functions like length
+    % TODO: support compound guard expressions: when is_list(L); length(List) == 6; is_tuple(T)
+    {0, [{call, F} || F <- lists:filter(starts_with("is_"), builtins())]};
+
+complete([], [{atom,1,FunctionOrModule}|_]) ->
+    % select modules
+    Prefix = atom_to_list(FunctionOrModule),
+    {string:len(Prefix), [{call, F} || F <- lists:filter(starts_with(Prefix), builtins())] ++
+    [{module, M} || M <- lists:filter(starts_with(Prefix), lists:sort(erlang:loaded()))]};
+complete(Local, [{atom,1,FunctionOrModule}|_]) ->
+    % select builtin calls
+    % select local calls
+    % select modules
+    Prefix = atom_to_list(FunctionOrModule),
+    {string:len(Prefix), [{call, F} || F <- lists:filter(starts_with(Prefix), Local:module_info(exports) ++ builtins())] ++
+    [{module, M} || M <- lists:filter(starts_with(Prefix), lists:sort(erlang:loaded()))]};
+
+complete(_, _) -> {0, []}.
+
+builtins() ->
+    lists:filter(fun({F,A}) -> erlang:is_builtin(erlang, F, A) end, erlang:module_info(exports)).
+
+starts_with(String) ->
+    Len = string:len(String),
+    fun({Atom,_}) ->
+        case string:substr(atom_to_list(Atom), 1, Len) of
+            String -> true;
+            _ -> false
+        end;
+    (Atom) ->
+        case string:substr(atom_to_list(Atom), 1, Len) of
+            String -> true;
+            _ -> false
+        end
+    end.
Index: Support/completion/src/tm_complete.erl
===================================================================
--- Support/completion/src/tm_complete.erl	(revision 0)
+++ Support/completion/src/tm_complete.erl	(revision 0)
@@ -0,0 +1,40 @@
+-module (tm_complete).
+-export ([string/1, string/2]).
+
+string(String) -> string([], String).
+string(Local, String) -> 
+    {PrefixLength, Options} = complete:string(Local, String),
+    Choice = users_choice(Options),
+    snippet(PrefixLength, Choice).
+
+users_choice([Option]) -> Option;
+users_choice(Options) ->
+    Menu = menu(Options),
+    Selection = tm_menu:selection(Menu),
+    option(Selection, Options, Menu).
+
+menu([{fun_ref, {Function, Arity}}|Options]) ->
+    [lists:flatten(io_lib:format("~w/~w", [Function, Arity]))|menu(Options)];
+menu([{call, {Function, Arity}}|Options]) ->
+    [lists:flatten(io_lib:format("~w/~w", [Function, Arity]))|menu(Options)];
+menu([{module, Module}|Options]) -> [atom_to_list(Module)|menu(Options)];
+menu([_|Options]) -> menu(Options);
+menu([]) -> [].
+
+option([], _, _) -> "";
+option(Selection, [Option|_], [Selection|_]) -> Option;
+option(Selection, [_|Options], [_|Menu]) -> option(Selection, Options, Menu).
+
+snippet(L, {fun_ref, {F, A}}) -> io_lib:format("~s/~w", [trim(L, F), A]);
+snippet(L, {call, {F, A}}) -> io_lib:format("~s(~s)", [trim(L, F), args(A)]);
+snippet(L, {module, M}) -> trim(L, M);
+snippet(_, _) -> "".
+
+trim(PrefixLength, Atom) -> string:substr(atom_to_list(Atom), PrefixLength + 1).
+
+args(0) -> "";
+args(Arity) -> args(Arity, 1).
+args(Arity, Arity) -> io_lib:format("${~w:Arg~w}", [Arity, Arity]);
+args(Arity, N) ->
+    [io_lib:format("${~w:Arg~w}, ", [N, N])|
+    args(Arity, N + 1)].
Index: Support/completion/src/Makefile
===================================================================
--- Support/completion/src/Makefile	(revision 0)
+++ Support/completion/src/Makefile	(revision 0)
@@ -0,0 +1,9 @@
+include ../support/include.mk
+
+all: $(EBIN_FILES)
+
+debug:
+	$(MAKE) DEBUG=-DDEBUG
+
+clean:
+	rm -rf $(EBIN_FILES)
Index: Support/completion/support/include.mk
===================================================================
--- Support/completion/support/include.mk	(revision 0)
+++ Support/completion/support/include.mk	(revision 0)
@@ -0,0 +1,47 @@
+## -*- makefile -*-
+
+######################################################################
+## Erlang
+
+ERL := erl
+ERLC := $(ERL)c
+
+INCLUDE_DIRS := ../include $(wildcard ../deps/*/include)
+EBIN_DIRS := $(wildcard ../deps/*/ebin)
+ERLC_FLAGS := -W $(INCLUDE_DIRS:../%=-I ../%) $(EBIN_DIRS:%=-pa %)
+
+ifndef no_debug_info
+  ERLC_FLAGS += +debug_info
+endif
+
+ifdef debug
+  ERLC_FLAGS += -Ddebug
+endif
+
+EBIN_DIR := ../ebin
+DOC_DIR  := ../doc
+EMULATOR := beam
+
+ERL_SOURCES := $(wildcard *.erl)
+ERL_HEADERS := $(wildcard *.hrl) $(wildcard ../include/*.hrl)
+ERL_OBJECTS := $(ERL_SOURCES:%.erl=$(EBIN_DIR)/%.$(EMULATOR))
+ERL_DOCUMENTS := $(ERL_SOURCES:%.erl=$(DOC_DIR)/%.html)
+ERL_OBJECTS_LOCAL := $(ERL_SOURCES:%.erl=./%.$(EMULATOR))
+APP_FILES := $(wildcard *.app)
+#EBIN_FILES = $(ERL_OBJECTS) $(ERL_DOCUMENTS) $(APP_FILES:%.app=../ebin/%.app)
+EBIN_FILES = $(ERL_OBJECTS) $(APP_FILES:%.app=../ebin/%.app)
+EBIN_FILES_NO_DOCS = $(ERL_OBJECTS) $(APP_FILES:%.app=../ebin/%.app)
+MODULES = $(ERL_SOURCES:%.erl=%)
+
+../ebin/%.app: %.app
+	cp $< $@
+
+$(EBIN_DIR)/%.$(EMULATOR): %.erl
+	$(ERLC) $(ERLC_FLAGS) -o $(EBIN_DIR) $<
+
+./%.$(EMULATOR): %.erl
+	$(ERLC) $(ERLC_FLAGS) -o . $<
+
+$(DOC_DIR)/%.html: %.erl
+	$(ERL) -noshell -run edoc file $< -run init stop
+	mv *.html $(DOC_DIR)
Index: Support/completion/Makefile
===================================================================
--- Support/completion/Makefile	(revision 0)
+++ Support/completion/Makefile	(revision 0)
@@ -0,0 +1,8 @@
+all:
+	(cd src;$(MAKE))
+
+test:
+	(cd src;$(MAKE) test)
+
+clean:
+	(cd src;$(MAKE) clean)
