Contributing Code
We welcome every contribution to this project. If you haven't checked out contribute page, do it now so you get a simple explanation of our contribution model. This page covers the technical or more specific details.
Although welcome, contributions must respect few rules imposed by the project:
- Code must respect our Coding Style (see section below);
- Code must be written and commented in English;
- Code should not be malicious or discriminative;
- Code should be tested (including valgrind) before submitted;
- Contributed code should match the project License;
- Every contributor keeps its Copyright (no assignment required).
Please refer to our Guidelines before sending patches. There we explain how to properly create patches and get them delivered to our mail list (sourceforge's mail list is quite restrictive and often patches get stripped from mails).
Using What we Already Provide
EFL is quite extensive and used in many different areas. Before starting your project and choosing what to use, check at EFL and EFLOverview if modules provide that feature, or infrastructure that you can use to get your solution.
For instance as a reminder of often forgotten features:
- Eina provides data types (list, hash, array...), logging, safety checks, module loading and more. Before introducing printf() to debug, silently ignore errors or start dlopen()ing, check that library;
- Ecore provides main loop and system integration that includes threads and networking. Consider it before using threads, networking, polling/reading from file descriptors;
- Eio provides efficient I/O to file system, like asynchronous copy, move, stat and directory listing;
- Edje provides theme capabilities and is good for creating layouts;
- Elementary provides lots of efficient handling widgets for lists, text input and multitude of helpers.
Creating New Features or Infrastructure
Although we provide a lot, that is not enough. Before starting to code a new feature, be in existing EFL, a new library or in your own application, talk to developers at IRC (#edevelop) or even better, the enlightenment-devel mail list. We probably have ideas on how to get it done efficiently, problems that kept us away from such thing (doomed features) and it will save future problems.
Testing & Debugging
Before submitting code to SVN or mail list, always test it for errors. Both positive (expected values/behavior) and negative tests. Run your code inside valgrind to ensure memory access is correct and it does not leak.
Read more about how to debug our software in the article about Debugging.
Editors
We have developers that use the following editors to work with Enlightenment technologies. We recommend reading the specific editor pages to be aided to follow our coding style. In alphabetical order:
Coding Style
Our coding style is quite particular, may look strange at first sight, but that's what we use and we'll just take code that respects it.
General rules:
- ALWAYS KEEP EXISTING CODING STYLE Even if it's different from this, do not change existing coding style as you introduce new code. If you want, send different/sequential patches. New code should always keep the coding style of its surroundings;
- no tabs (we used to, so you may find in code. but do not insert more!)
- 3 spaces indent after braces ("{");
- 2 spaces indent after keywords: if, for, while, do, switch, case...
- 1 space indent before 'case' (after switch's brace);
- 1 space before parenthesis for keywords: if, for, while, switch
- no spaces before parenthesis for functions (and macros), including sizeof().
- 80 columns code whenever possible;
- short if (cond) action are fine as single line;
- use parenthesis for every clause or math;
- functions have lower case names, separated by underline (like_this);
- structures are declared with leading underscore and typedef'ed with capitalized, separated by underline (typedef struct _Like_This Like_This);
- namespaced code: <module>_<object>_<specializations>_<action>, example evas_object_color_get(). It is clear that you're getting the color of an object of evas module;
- action is the last part of function names. evas_object_color_get() not
evas_object_get_color() - properly mark symbol visibility. static (local to file) and EAPI (publicly exported). Non marked symbols tend to be exported just to the containing module by means of linker -fvisibility=hidden;
- properly mark pointer const for getters or when it should not be modified, both arguments and return;
- short names for narrow scope (o for object, x/y/w/h for geometry, r/g/b/a for colors...);
- optionally use underscore to prefix local/private symbols;
- function forward declaration/prototype should be a single line;
- function definition should have the return at one line, then function name starts at next line, column 0;
Examples
If statements
Short statements can be in single line (good for error checking):
if (!p) return; if (!p) return -EINVAL;
Longer statements, with a single operation are in separated lines without braces:
if (!module_object_initialized()) module_object_initialize();
Multiple statements go with braces (note that indentation changes with braces:)
if (!module_object_initialized()) { module_object_initialize(); EINA_LOG_DBG("module was initialized"); }
Keep the smallest branch first, helps reading:
if (cond < 0) do_something_about_it_long(); else { int i; for (i = 0; i < cond; i++) call_cond(i); } if (cond < 0) handle_negative(); else { int i; for (i = 0; i < cond; i++) call_cond(i); }
Add parenthesis around all conditions:
if (a) ... if (!a) ... if ((a) && (b))... if ((!a) && (b))...
While/For/Do/Switch statements
Similar to examples in If statements:
while (lst) lst = eina_list_remove_list(lst, lst); while ((lst != lst_last) && (lst != lookup)) lst = lst_find_something(lst); for (i = 0; ((i < 10) && (i * 10 < something()); i++) { if (i % 2) proc_even(i); else proc_odd(i) } do { process_fds(); process_timers(); process_idlers(); } while (run); switch (action) { case ACTION_NEW: return _new(); case ACTION_DEL: { free(xyz); return NULL; } };
Structures
typedef struct _My_Class My_Class; struct _My_Class { void *base; unsigned int references; };
Functions
Note: Just use forward declarations if required. Try to avoid them.
static void my_class_ref(My_Class *cls); static void my_class_ref(My_Class *cls) { if (!cls) return; cls->references++; }
Math and Bitwise operations
Use parenthesis to make clear what you want, even if the operator precedence is obvious to you.
a = (b * c) / d; a = b * (c / d); a = (b * c) + d; a = (b / c) - d; a = ((b * c) + d) / e; a = (b & 0xf) << 8; a = (b << 8) & 0xf0; a = (b | c) ^ d; a = ((b & c) | d) & 0x00ff00;
