diff --git a/Common/Bindings.cpp b/Common/Bindings.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..049026c19acb59d0f967157a7750fa3d545d796d
--- /dev/null
+++ b/Common/Bindings.cpp
@@ -0,0 +1,13 @@
+#include <stdarg.h>
+#include "Bindings.h"
+#include <stdio.h>
+void methodBinding::setArgNames(const char *arg1, ...) {
+  va_list ap;
+  va_start(ap,arg1);
+  const char * name=arg1;
+  while(name!=NULL){
+    _argNames.push_back(name);
+    name = va_arg(ap,const char *);
+  }
+  va_end(ap);
+}
diff --git a/Common/Bindings.h b/Common/Bindings.h
index 0b254c188180ee00381285c693b1f4fb0b03d464..fb3c408fb3715d5361d700b8873565ef85aa204a 100644
--- a/Common/Bindings.h
+++ b/Common/Bindings.h
@@ -1,18 +1,23 @@
 #ifndef _BINDINGS_H_
 #define _BINDINGS_H_
 #include <string>
-#include <list>
+#include <vector>
 #include <typeinfo>
-#include "GmshConfig.h"
 
 class methodBinding{
   std::string _description;
+  std::vector<std::string> _argNames;
   public:
-  void setArgNames(std::string arg1, ...){}
+  inline const std::vector<std::string> &getArgNames()const{
+    return _argNames;
+  }
+  void setArgNames(const char * arg1, ...);
   void setDescription(std::string description){_description=description;}
   inline const std::string getDescription() const {return _description;}
 };
 
+
+
 #if defined(HAVE_LUA)
 #include "LuaBindings.h"
 #else  //no bindings
diff --git a/Common/BindingsTypeName.h b/Common/BindingsTypeName.h
new file mode 100644
index 0000000000000000000000000000000000000000..0dab638b6a5c273deddf40ba3528d2e08d63fb12
--- /dev/null
+++ b/Common/BindingsTypeName.h
@@ -0,0 +1,158 @@
+#ifndef BINDINGS_TYPE_NAME_H
+#define BINDINGS_TYPE_NAME_H
+#include <vector>
+#include <string>
+/*** store a unique static class name for each binded class ***/
+template <typename type>
+class className{
+  static std::string _name;
+  public:
+  static void set(std::string name){
+    if(_name!=""){
+      throw;
+    }
+    _name=name;
+  }
+  static const std::string &get(){
+    if(_name==""){
+      throw;
+    }
+    return _name;
+  }
+};
+template<typename type>
+std::string  className<type>::_name;
+
+template <>
+class className<std::string>{
+  public:
+  static const std::string get(){
+    return "string";
+  }
+};
+template <>
+class className<int>{
+  public:
+  static const std::string get(){
+    return "int";
+  }
+};
+template <>
+class className<double>{
+  public:
+  static const std::string get(){
+    return "double";
+  }
+};
+template <>
+class className<void>{
+  public:
+  static const std::string get(){
+    return "void";
+  }
+};
+template <typename t>
+class className<t*>{
+  public:
+  static const std::string get(){
+    return className<t>::get();
+  }
+};
+template <typename t>
+class className<const t &>{
+  public:
+  static const std::string get(){
+    return className<t>::get();
+  }
+};
+
+template <typename cb>
+class argTypeNames;
+template <typename tr, typename tObj, typename t0, typename t1, typename t2, typename t3>
+class argTypeNames<tr (tObj::*)(t0,t1,t2,t3)>{
+  public:
+  static void get(std::vector<std::string> &names){
+    names.clear();
+    names.push_back(className<tr>::get());
+    names.push_back(className<t0>::get());
+    names.push_back(className<t1>::get());
+    names.push_back(className<t2>::get());
+    names.push_back(className<t3>::get());
+  }
+};
+template <typename tr, typename tObj, typename t0, typename t1, typename t2>
+class argTypeNames<tr (tObj::*)(t0,t1,t2)>{
+  public:
+  static void get(std::vector<std::string> &names){
+    names.clear();
+    names.push_back(className<tr>::get());
+    names.push_back(className<t0>::get());
+    names.push_back(className<t1>::get());
+    names.push_back(className<t2>::get());
+  }
+};
+template <typename tr, typename tObj, typename t0, typename t1>
+class argTypeNames<tr (tObj::*)(t0,t1)>{
+  public:
+  static void get(std::vector<std::string> &names){
+    names.clear();
+    names.push_back(className<tr>::get());
+    names.push_back(className<t0>::get());
+    names.push_back(className<t1>::get());
+  }
+};
+template <typename tr, typename tObj, typename t0>
+class argTypeNames<tr (tObj::*)(t0)>{
+  public:
+  static void get(std::vector<std::string> &names){
+    names.clear();
+    names.push_back(className<tr>::get());
+    names.push_back(className<t0>::get());
+  }
+};
+template <typename tr, typename tObj>
+class argTypeNames<tr (tObj::*)()>{
+  public:
+  static void get(std::vector<std::string> &names){
+    names.clear();
+    names.push_back(className<tr>::get());
+  }
+};
+template <typename cb>
+class argTypeNames;
+template <typename tr, typename tObj, typename t0, typename t1, typename t2, typename t3>
+class argTypeNames<tr (tObj::*)(t0,t1,t2,t3)const>{
+  public:
+  static void get(std::vector<std::string> &names){
+    argTypeNames<tr (tObj::*)(t0,t1,t2,t3)>::get(names);
+  }
+};
+template <typename tr, typename tObj, typename t0, typename t1, typename t2>
+class argTypeNames<tr (tObj::*)(t0,t1,t2)const>{
+  public:
+  static void get(std::vector<std::string> &names){
+    argTypeNames<tr (tObj::*)(t0,t1,t2)>::get(names);
+  }
+};
+template <typename tr, typename tObj, typename t0, typename t1>
+class argTypeNames<tr (tObj::*)(t0,t1)const>{
+  public:
+  static void get(std::vector<std::string> &names){
+    argTypeNames<tr (tObj::*)(t0,t1)>::get(names);
+  }
+};
+template <typename tr, typename tObj, typename t0>
+class argTypeNames<tr (tObj::*)(t0)const>{
+  public:
+  static void get(std::vector<std::string> &names){
+    argTypeNames<tr (tObj::*)(t0)>::get(names);
+  }
+};
+template <typename tr, typename tObj>
+class argTypeNames<tr (tObj::*)()const>{
+  public:
+  static void get(std::vector<std::string> &names){
+    argTypeNames<tr (tObj::*)()>::get(names);
+  }
+};
+#endif
diff --git a/Common/CMakeLists.txt b/Common/CMakeLists.txt
index f1eda826c322436a5e382556133f570599b2480b..b0c8624f9e3ff5739939ce4cdb4079e6086f942f 100644
--- a/Common/CMakeLists.txt
+++ b/Common/CMakeLists.txt
@@ -23,6 +23,7 @@ set(SRC
   TreeUtils.cpp avl.cpp
   MallocUtils.cpp
   ConnectionManager.cpp
+  Bindings.cpp
 )
 
 file(GLOB HDR RELATIVE ${CMAKE_SOURCE_DIR}/Common *.h) 
diff --git a/Common/LuaBindings.cpp b/Common/LuaBindings.cpp
index 1b98e8ca00ff3b305e4f1e9310e2287ed02dcf2c..7a8dee96bdf5971cbc069f543eb884d0637ad1bf 100644
--- a/Common/LuaBindings.cpp
+++ b/Common/LuaBindings.cpp
@@ -41,13 +41,30 @@ const char *colorBlue = "\033[1;34m";
 const char *colorDefault = "\033[0m";
 const char *colorBold = "\033[1m";
 
+static void print_method(std::string name, luaMethodBinding *mb, bool isConstructor=false) {
+  std::vector<std::string> argTypeNames;
+  mb->getArgTypeNames(argTypeNames);
+  std::cout<<"  ";
+  if(!isConstructor)
+    std::cout<<colorBold<<argTypeNames[0];
+  std::cout<<colorBlue<<" "<<name<<colorDefault<<colorBold<<" (";
+  for(int i=1;i< argTypeNames.size(); i++){
+    if(i!=1)
+      std::cout<<", ";
+    std::cout<<colorBold<<argTypeNames[i]<<colorDefault;
+    if(mb->getArgNames().size()>i-1)
+      std::cout<<" "<<mb->getArgNames()[i-1];
+  }
+  std::cout<<colorBold<<")\n"<<colorDefault;
+  const std::string description=mb->getDescription();
+  std::cout<<(description.empty()?"no help available":description) <<"\n";
+
+}
 static void list_methods(classBinding *cb){
   if(cb->methods.size())
-    std::cout<<colorBold<<"Methods from "<<cb->getClassName()<<colorDefault<<"\n";
+    std::cout<<colorGreen<<"Methods from "<<cb->getClassName()<<colorDefault<<"\n";
   for(std::map<std::string,luaMethodBinding *>::iterator it = cb->methods.begin(); it!=cb->methods.end(); it++){
-    std::cout<<colorBlue<<"  "<<it->first<<colorDefault<<" : ";
-    const std::string description=it->second->getDescription();
-    std::cout<<(description.empty()?"no help available":description) <<"\n";
+    print_method(it->first,it->second);
   }
   if(cb->getParent())
     list_methods(cb->getParent());
@@ -76,12 +93,17 @@ static int lua_help (lua_State *L){
     const std::string description=cb->getDescription();
     std::cout<<(description.empty()?"no help available":description) <<"\n";
     std::cout<<"\n";
+    if(cb->getConstructor()){
+      std::cout<<colorGreen<<"Constructor"<<colorDefault<<"\n";
+      print_method(className,cb->getConstructor(),true);
+      std::cout<<"\n";
+    }
     list_methods(cb);
     std::cout<<"\n";
     if(cb->children.size()){
-      std::cout<<colorBold<<"Children of "<<cb->getClassName()<<colorDefault<<"\n";
+      std::cout<<colorGreen<<"Children of "<<cb->getClassName()<<colorDefault<<"\n";
       for(std::set<classBinding *>::iterator it = cb->children.begin(); it!=cb->children.end(); it++){
-        std::cout<<"  "<<colorGreen<<(*it)->getClassName()<<colorDefault<<" : ";
+        std::cout<<"  "<<colorBlue<<(*it)->getClassName()<<colorDefault<<" : ";
         const std::string description=(*it)->getDescription();
         std::cout<<(description.empty()?"no help available":description) <<"\n";
       }
@@ -167,15 +189,15 @@ binding::binding(){
 
   // Register Lua bindings
   GModel::registerBindings(this);
+  fullMatrix<double>::registerBindings(this);
+  function::registerBindings(this);
+  dgConservationLaw::registerBindings(this);
   dgSystemOfEquations::registerBindings(this);
   dgBoundaryCondition::registerBindings(this);
-  dgConservationLaw::registerBindings(this);
   dgConservationLawShallowWater2dRegisterBindings(this);
   dgConservationLawWaveEquationRegisterBindings(this);
   dgConservationLawAdvectionRegisterBindings(this);
   dgPerfectGasLaw2dRegisterBindings(this);
-  fullMatrix<double>::registerBindings(this);
-  function::registerBindings(this);
   functionLua::registerBindings(this);
   function::registerDefaultFunctions();
   MVertex::registerBindings(this);
diff --git a/Common/LuaBindings.h b/Common/LuaBindings.h
index 6e28eb222e8ecc66840a1195003f9e25da492bc4..f0e4c36e31d30bd3592766ca023f3bdb5ee3bda4 100644
--- a/Common/LuaBindings.h
+++ b/Common/LuaBindings.h
@@ -1,17 +1,20 @@
 #ifndef _LUA_BINDINGS_H_
 #define _LUA_BINDINGS_H_
 
+#include <map>
+#include <vector>
+#include <set>
+#include "GmshConfig.h"
+#include "GmshMessage.h"
 #include "Bindings.h"
 
 #ifdef HAVE_LUA
-//#include "BindingsDocTemplates.h"
+#include "BindingsTypeName.h"
 
 extern "C" {
 #include "lua.h"
 #include "lauxlib.h"
 }
-#include <vector>
-#include <set>
 
 class classBinding;
 class binding {
@@ -27,26 +30,6 @@ class binding {
   classBinding *addClass(std::string className);
 };
 
-/*** store a unique static class name for each binded class ***/
-template <typename type>
-class className{
-  static std::string _name;
-  public:
-  static void set(std::string name){
-    if(_name!="")
-      throw;
-    _name=name;
-  }
-  static const std::string &get(){
-    if(_name=="")
-      throw;
-    return _name;
-  }
-};
-template<typename type>
-std::string  className<type>::_name;
-
-
 
 
 /*** lua Stack : templates to get/push value from/on the lua stack ***/
@@ -55,7 +38,7 @@ template<class type>
 class luaStack {
   public:
   static type get(lua_State *L, int ia){
-    printf("error cannot get generic class in lua, only pointers are implemented\n");
+    Msg::Error("error cannot get generic class in lua, only pointers are implemented\n");
   }
   static void push(lua_State *L, type obj){
     Msg::Error("cannot push generic class in lua, only pointers are implemented\n");
@@ -309,6 +292,8 @@ static int luaCall(lua_State *L,void (tObj::*_f)() const) {
   return 0;
 };
 
+
+
 //non const, no return
 template <typename tObj, typename t0, typename t1, typename t2, typename t3>
 static int luaCall(lua_State *L,void (tObj::*_f)(t0,t1,t2,t3)) {
@@ -337,6 +322,9 @@ static int luaCall(lua_State *L,void (tObj::*_f)()) {
 };
 
 
+/*** arg names ***/
+
+
 /*** actual bindings classes ***/
 class luaMethodBinding :public methodBinding{
   public:
@@ -348,6 +336,7 @@ class luaMethodBinding :public methodBinding{
   luaMethodBinding(){
     _luaname="";
   }
+  virtual void getArgTypeNames(std::vector<std::string> &names){};
 };
 
 template <typename cb>
@@ -360,8 +349,8 @@ class methodBindingT:public luaMethodBinding {
   int call (lua_State *L) {
     return luaCall(L,_f);
   }
-  void getArgNames(std::string &returnTypeName, std::vector<std::string> &argTypeName) {
-    getArgNames(_f,returnTypeName,argTypeName);
+  void getArgTypeNames(std::vector<std::string> &names) {
+    argTypeNames<cb>::get(names);
   }
 };
 
@@ -373,6 +362,9 @@ class constructorBindingT:public luaMethodBinding {
     (luaStack<tObj*>::push(L,new tObj(luaStack<t0>::get(L,1),luaStack<t1>::get(L,2),luaStack<t2>::get(L,3), luaStack<t3>::get(L,4))));
     return 1;
   }
+  void getArgTypeNames(std::vector<std::string> &names) {
+    argTypeNames<void (tObj::*)(t0,t1,t2,t3)>::get(names);
+  }
 };
 
 template <typename tObj>
@@ -383,6 +375,9 @@ class constructorBindingT<tObj,void,void,void,void>:public luaMethodBinding {
     (luaStack<tObj*>::push(L,new tObj()));
     return 1;
   }
+  void getArgTypeNames(std::vector<std::string> &names) {
+    argTypeNames<void (tObj::*)()>::get(names);
+  }
 };
 template <typename tObj, typename t0>
 class constructorBindingT<tObj,t0,void,void,void>:public luaMethodBinding {
@@ -392,6 +387,9 @@ class constructorBindingT<tObj,t0,void,void,void>:public luaMethodBinding {
     (luaStack<tObj*>::push(L,new tObj(luaStack<t0>::get(L,1))));
     return 1;
   }
+  void getArgTypeNames(std::vector<std::string> &names) {
+    argTypeNames<void (tObj::*)(t0)>::get(names);
+  }
 };
 template <typename tObj, typename t0, typename t1>
 class constructorBindingT<tObj,t0,t1,void,void>:public luaMethodBinding {
@@ -401,6 +399,9 @@ class constructorBindingT<tObj,t0,t1,void,void>:public luaMethodBinding {
     (luaStack<tObj*>::push(L,new tObj(luaStack<t0>::get(L,1),luaStack<t1>::get(L,2))));
     return 1;
   }
+  void getArgTypeNames(std::vector<std::string> &names) {
+    argTypeNames<void (tObj::*)(t0,t1)>::get(names);
+  }
 };
 template <typename tObj, typename t0, typename t1, typename t2>
 class constructorBindingT<tObj,t0,t1,t2,void>:public luaMethodBinding {
@@ -410,11 +411,15 @@ class constructorBindingT<tObj,t0,t1,t2,void>:public luaMethodBinding {
     (luaStack<tObj*>::push(L,new tObj(luaStack<t0>::get(L,1),luaStack<t1>::get(L,2),luaStack<t2>::get(L,3))));
     return 1;
   }
+  void getArgTypeNames(std::vector<std::string> &names) {
+    argTypeNames<void (tObj::*)(t0,t1,t2)>::get(names);
+  }
 };
 
 class classBinding {
   std::string _className;
   binding *_b;
+  luaMethodBinding *_constructor;
   static int callMethod(lua_State *L) {
     return  static_cast<luaMethodBinding*>(lua_touserdata(L, lua_upvalueindex(1)))->call(L); 
   }
@@ -444,17 +449,22 @@ class classBinding {
     lua_pushcclosure(L, callMethod, 1);
     lua_setfield(L, mt,"__call");
     lua_pop(L,2);
+    _constructor=constructor;
   }
   //for the doc
   std::string _description;
   classBinding *_parent;
 public:
   std::set<classBinding *> children;
+  inline luaMethodBinding *getConstructor(){
+    return _constructor;
+  }
   // get userdata from Lua stack and return pointer to T object
   classBinding(binding *b, std::string name){
     _b=b;
     lua_State *L = _b->L;
     _className=name;
+    _constructor=NULL;
 
     // there are 3 tables involved :
     // methods : the table of the C++ functions we bind (exept constructor)
diff --git a/Numeric/fullMatrix.cpp b/Numeric/fullMatrix.cpp
index 8a75bc796d2c329a96fff7175aaca66491ba03ad..865a4b41e8faed26065ade38b9265f05378683dd 100644
--- a/Numeric/fullMatrix.cpp
+++ b/Numeric/fullMatrix.cpp
@@ -293,10 +293,17 @@ template<>
 void fullMatrix<double>::registerBindings(binding *b)
 {
   classBinding *cb = b->addClass<fullMatrix<double> >("fullMatrix");
-  cb->addMethod("size1", &fullMatrix<double>::size1);
-  cb->addMethod("size2", &fullMatrix<double>::size2);
-  cb->addMethod("get", &fullMatrix<double>::get);
-  cb->addMethod("set", &fullMatrix<double>::set);
-  cb->addMethod("gemm", &fullMatrix<double>::gemm);
-  cb->setConstructor<fullMatrix<double>,int,int>();
+  methodBinding *cm;
+  cm = cb->addMethod("size1", &fullMatrix<double>::size1);
+  cm->setDescription("return the number of rows in the matrix");
+  cm = cb->addMethod("size2", &fullMatrix<double>::size2);
+  cm->setDescription("return the number of columns in the matrix");
+  cm = cb->addMethod("get", &fullMatrix<double>::get);
+  cm->setArgNames("i","j",NULL);
+  cm->setDescription("return the (i,j) entry of the matrix");
+  cm = cb->addMethod("set", &fullMatrix<double>::set);
+  cm->setArgNames("i","j","v",NULL);
+  cm->setDescription("set the (i,j) entry of the matrix to v");
+  cm = cb->addMethod("gemm", &fullMatrix<double>::gemm);
+  cm = cb->setConstructor<fullMatrix<double>,int,int>();
 }