Erlang/OTP Forums

Author Message

<  Advanced Erlang/OTP  ~  Yaws Appmods

seancharles
Posted: Wed Jul 25, 2007 8:28 am Reply with quote
User Joined: 18 Jul 2007 Posts: 57
Hi,

I am fairly new to Erlang and yaws and I have a question about appmod development... is it possible to have yaws automatically compile and load an appmod file when it has changed ?

Currently I have this process:

-edit my 'appmod'.erl with emacs
-save it
-compile it from the shell
-restart yaws

this is far from ideal and I am sure that I have missed something important! it took me ages to find the -d flag!

the --pa flag is crucial too! Can this be made to work recursively like a Java classpath for example or do I have to specify *every single path* beneath it ?
So,

Can I issue the c(myappmode). at the interactive prompt for yaws ? Currently it doesn't seem to play ball.

Anything that you can tell me to enhance the web-dev experience here will be greatly appreciated.

Currently I have travelled from C++, Smalltalk, SBCL, Scheme and finally, I found Erlang after getting bored with Haskell and OCAML.

Erlang just 'feels' right; reminds me of my early days (21 years ago) of working in embedded telemetry and u-processor systems

Smile
Thanks
Sean Charles
View user's profile Send private message
Mazen
Posted: Wed Jul 25, 2007 9:09 am Reply with quote
User Joined: 20 Jul 2006 Posts: 164 Location: London
Hi seancharles,

First of all you shouldn't have to restart yaws in order to use your new appmod. A simple
Code:
l(module).
should take care of business.

Having said that, you should look into creating an Emakefile (http://www.erlang.org/doc/man/make.html). Then using
Code:
make:all([load]).
will compile all files and load them. In other words your new process would be:

1) Edit 'appmod.erl'
2) Save it
3) Invoke 'make:all([load]).'

I'm 99% sure that you can have emacs run step 3 when performing step 2. Maybe an Emacs guru/google search will help you out Smile

/M
View user's profile Send private message
seancharles
Posted: Wed Jul 25, 2007 12:57 pm Reply with quote
User Joined: 18 Jul 2007 Posts: 57
Mazen,

Thanks!!!

I am going to try all of this right now... just got back from a meeting. ZZZZ! Smile

I have written a few Emacs macros, I know LISP and all that jazz so once I get the proof of concept I'll hack a macro and bind it to the save operation , I hope!

I really like Erlang and I like Yaws. I have looked at ErlyWeb but I don't have the time to take on board that much new stuff right now.

The site I am developing will (hopefully) be hosted by me and will be a 'real world' site coming soon... as soon as I get it finished in between a dozen day jobs!

Many thanks,
I 'll let you know!
Smile
Sean
View user's profile Send private message
seancharles
Posted: Wed Jul 25, 2007 4:26 pm Reply with quote
User Joined: 18 Jul 2007 Posts: 57
Having learned a few tricks and feeling happier about appmode development with yaws, I did some looking at the source code with a view to adding the following enhancement.

Currently the '-d' flag turns of caching so that you can edit / refresh as web developers do until they get it right.

I am proposing that the '-d' flag also adds the following behavior: before executing the 'module:out(A)' handler it should first re-compile that module and reload it so that it is always up to date.

Then you can optimise and only do the above if the file has changed ie lastmod dates are different in memory / on disk.

The file: yaws_server.erl has the function 'handle_ut(CliSock,ARG,UT,N)' which decides what to do with the request.

There is a handler for 'appmod':
Code:

   appmod ->
       yaws:outh_set_dyn_headers(Req, H, UT),
        {Mod, PathData} = UT#urltype.data,
        A2 = ARG#arg{appmoddata = PathData,  % trail
           appmod_prepath = UT#urltype.path}, % head
       deliver_dyn_part(CliSock,
              0, "appmod",
              N,
              A2,UT,
              fun(A)->Mod:out(A) end,
              fun(A)->finish_up_dyn_file(A, CliSock)
              end
             );

I think that just before the 'deliver_dyn_part' call is executed, a check could be made for '-d' mode being in effect and if this was true, then we can reload the module just before making the call.

I think this would be 'a good thing' and would make life a whole lot easier.

I am going to try to do this as soon as I can as I think the time spent will teach me a lot about Erlang and yaws, and how to write great code

Smile
Stay toooned...
View user's profile Send private message
seancharles
Posted: Thu Jul 26, 2007 10:06 pm Reply with quote
User Joined: 18 Jul 2007 Posts: 57
It took some digging but I managed to come up with a solution that allows Emacs to cause yaws to reload an 'appmod' source file when you save the file in Emacs. It also has the advantage of showing you compile errors in the yaws console if you have it showing, as I usually do.

Here we go... you need 'curl' installed on your machine, I am using OS X 10.4 on an iNTEL iMac with no problems at all.

Edit your yaws.config server entry and add the following line to it, this sets up the web service call for emacs to use:

appmods = <emacs,emacs>

"emacs appmod:"
Save this as emacs.erl in the same directory as your appmod modules:
Code:

-module(emacs).
-author("sean dot charles at objitsu dot com").

%% Change to match your erlang installation
-include("/usr/local/lib/yaws/include/yaws_api.hrl").
-export([out/1]).

%% ------------------------------------------------------------
%% This causes yaws to compile and reload the named module.
%% A corresponding emacs hook will make this call every time we
%% C-x C-s in a buffer ending with .erl.
%%
%% This should provide for a 'seamless' integration between the
%% emacs editor and the yaws application being developed and
%% make life a whole lot easier for developers everywhere.
%%
%% Assumes that the emacs argument is the ABSOLUTE file path
%% and uses that information to:
%%
%% 1)  cd("the containing directory").
%% 2)  c("the filename").
%%
%% Because Erlang and yaws are things of beauty and elegance,
%% this arrangement also provides the benefit of outputting all
%% compiler errors to the yaws console as well which means that
%% as soon as you save it you can see what went bang!
%%
%% This is 'almost' the beginning of a SLIME like IDE dare I
%% say it: you *could* send the compiler output back as the
%% return data from the request and display it emacs friendly
%% format... maybe another day!  :)
%%
%% You can run yaws from a shell inside emacs and have it in the
%% bottom part of the display, that way you can see your errors
%% as and when they happen.
%% ------------------------------------------------------------

out(A) ->
    Module  = filename:basename(A#arg.appmoddata),
    Mod_Dir = filename:dirname(A#arg.appmoddata),

    %% Write a message to the yaws console...
    io:format("!!! Emacs refreshed module: ~s~n", [Module]),

    io:format("!!! CD: ~w~n", [c:cd(Mod_Dir)]),
    io:format("!!!  C: ~w~n", [c:c(Module)]),
        ok.


Start yaws
Quote:
yaws -i -d --pa <what-you-want>


Compile and load the emacs module...
Code:

4> cd("dev/erlang/freeme/web/modules").
/Users/seancharles/Documents/Development/erlang/freeme/web/modules
ok
5> c(emacs).
{ok,emacs}
6>


.emacs file addition:
Code:

;; Change the localhost:8888 to match your server configuration
(defun yaws-reload ()
                (shell-command-to-string
                  (concat "curl -o /dev/null http://localhost:8888/emacs/"\
 (buffer-file-name) )))

(add-hook 'after-save-hook 'yaws-reload)


If anybody wants some help setting this up then PM via this site and I'll try to help. Now I have it working it is really really effective: edit, save, refresh, presto!

Smile
Sean
View user's profile Send private message
Mazen
Posted: Fri Jul 27, 2007 3:30 pm Reply with quote
User Joined: 20 Jul 2006 Posts: 164 Location: London
Cool Smile

Another idea would be to start up yaws on a node with Distel and connect the save mechanism to that instead. Would be a little bit more work I guess but would be nicer Smile but I like what you've done.

I'll try it out this weekend to see how it works Smile

/M
View user's profile Send private message
seancharles
Posted: Fri Jul 27, 2007 3:40 pm Reply with quote
User Joined: 18 Jul 2007 Posts: 57
Thanks.
I have been using it all day so far.

The only little 'quirk' is that I seem to have to launch emacs from the appmod directory so maybe I am not that good after all.

All I know is that it works 100% every time and my life has been a whole lot easier since.

I looked at Distel but was immediately turned off by it for some reason! I use SBCL+SLIME+EMACS a fair bit if I can too but Distel didn't click with me, plus I rolled my own and it worked! Smile

Thanks
If you have any hassles, mail me! I am seriously thinking about an interactive IDE for yaws development though!
View user's profile Send private message

Display posts from previous:  

All times are GMT
Page 1 of 1
This forum is locked: you cannot post, reply to, or edit topics.

Jump to:  

You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You cannot download files in this forum