[gimp] Add separate CODING_STYLE file
- From: Jehan <jehanp src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp] Add separate CODING_STYLE file
- Date: Mon, 2 Aug 2021 11:17:17 +0000 (UTC)
commit 1373bec64a1cb9b3ecf1cab383d55e3b228b8de7
Author: Stanislav Grinkov <43956-stanislavgrinkov users noreply gitlab gnome org>
Date: Wed May 26 08:49:54 2021 +0600
Add separate CODING_STYLE file
CODING_STYLE.md | 594 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
HACKING | 44 +----
2 files changed, 596 insertions(+), 42 deletions(-)
---
diff --git a/CODING_STYLE.md b/CODING_STYLE.md
new file mode 100644
index 0000000000..d8cc609c84
--- /dev/null
+++ b/CODING_STYLE.md
@@ -0,0 +1,594 @@
+# GIMP Coding Style
+
+This document describes the preferred coding style for the GIMP source code.
+It was strongly inspired by GNU's CODING_STYLE and developed from there.
+
+Coding style is a matter of consistency, readability, and maintenance; coding
+style is also completely arbitrary and a matter of taste. This document will
+use examples at the very least to provide authoritative and consistent answers
+to common questions regarding the coding style and will also try to identify the
+allowed exceptions.
+
+## Table of contents
+
+- [General rules](#general-rules)
+- [Dealing with the old code](#dealing-with-the-old-code)
+- [Indentation](#indentation)
+- [Braces](#braces)
+- [Whitespace](#whitespace)
+- [If-else code styling](#if-else-code-styling)
+- [Conditions](#conditions)
+- [Switch statement](#switch-statement)
+- [Functions](#functions)
+- [Macros](#macros)
+- [Includes](#includes)
+- [Structures](#structures)
+- [Memory management](#memory-management)
+- [API Documentation](#api-documentation)
+- [Public API](#public-api)
+- (__Sections below__)
+- [Private API](#private-api)
+- [Headers](#headers)
+- [](#)
+- [](#)
+- [](#)
+
+## General rules
+
+We recommend enabling the default git pre-commit hook that detects trailing
+whitespace and non-ASCII filenames for you and helps you to avoid corrupting
+GIMP's tree with it.
+
+In the terminal, navigate into your GIMP source code folder. Then do that as
+follows (one command at a time):
+
+```shell
+ cp -v .git/hooks/pre-commit.sample .git/hooks/pre-commit
+ chmod a+x .git/hooks/pre-commit
+```
+
+If any command above fails, visit your `.git/hooks/` folder and check for the
+existence of `pre-commit.sample` or `pre-commit` files.
+
+You might also find the `git-stripspace` utility helpful, which acts as a filter
+to remove trailing whitespace as well as initial, final, and duplicate blank
+lines.
+
+## Dealing with the old code
+
+__The new GIMP code should adhere to the style explained below.__ The existing
+GIMP code largely follows these conventions, but there are some differences like
+extra or missing whitespace, tabs instead of space, wrong formatting, etc.
+
+__Our policy is to update the style of a code block or function if and only if
+you happen to touch that code.__
+
+Please don't waste your time and reviewers' time with merge requests or patches
+with _only_ code style fixes unless you have push rights to the GIMP's
+repository.
+
+### Line width
+
+The recommended line width for source files is _80 characters_ whenever possible.
+Longer lines are usually an indication that you either need a function or a
+pre-processor macro.
+
+The point is to have clear code to read and not overly long lines. Don't break
+code into ugly and choppy parts to blindly follow this rule.
+
+Function definitions in the function forward declaration block don't have to
+obey the 80 characters limit. The only general rule for headers is to align the
+function definitions vertically in three columns.
+See more information in [Headers sections](#Headers)
+
+
+## Indentation
+
+Each new level is indented 2 or more spaces than the previous level:
+
+```c
+ if (condition)
+ single_statement ();
+```
+
+Use only __space characters__ to achieve this. Code indented with tabs will not
+be accepted into the GIMP codebase.
+
+Even if two spaces for each indentation level allow deeper nesting, GIMP favors
+self-documenting function names that can be quite long. For this reason, you
+should avoid deeply nested code.
+
+### Tab characters
+
+Use `\t` instead of literal tab inside the source code strings.
+
+## Braces
+
+Using blocks to group code is discouraged and must not be used in newly
+written code.
+
+```c
+int retval = 0;
+gbool condition = retval >= 0;
+
+statement_1 ();
+statement_2 ();
+
+ /* discouraged in newly written code */
+ {
+ int var1 = 42;
+ gboolean res = FALSE;
+
+ res = statement_3 (var1);
+ retval = res ? -1 : 1;
+ }
+```
+
+## Whitespace
+
+Except for one single newline at the end of the file, other empty lines (at the
+beginning and the end) of a file are not allowed.
+
+Always put a space before an opening parenthesis but never after:
+
+```c
+ /* valid */
+ if (condition)
+ do_my_things ();
+
+ /* valid */
+ switch (condition)
+ {
+ }
+
+ /* invalid */
+ if(condition)
+ do_my_things();
+
+ /* invalid */
+ if ( condition )
+ do_my_things ( );
+```
+
+Do not eliminate whitespace and newlines just because something would
+fit on 80 characters:
+
+```c
+ /* invalid */
+ if (condition) foo (); else bar ();
+```
+
+## If-else code styling
+
+Don't use curly braces for single statement blocks:
+
+```c
+ /* valid */
+ if (condition)
+ single_statement ();
+ else
+ another_single_statement (arg1);
+```
+
+In the case of multiple statements, put curly braces on another indentation level:
+
+```c
+ /* valid */
+ if (condition)
+ {
+ statement_1 ();
+ statement_2 ();
+ statement_3 ();
+ }
+
+ /* invalid */
+ if (condition) {
+ statement_1 ();
+ statement_2 ();
+ }
+
+ /* invalid */
+ if (condition)
+ {
+ statement_1 ();
+ statement_2 ();
+ }
+```
+
+The "no block for single statements" rule has only three exceptions:
+
+ ① _Both sides of the if-else statement_ must have curly braces when
+ either side of this if-else statement has braces or when
+ the single statement covers multiple lines, and it's followed
+ by else or else if (e.g., for functions with many arguments).
+
+```c
+ /* valid */
+ if (condition)
+ {
+ a_single_statement_with_many_arguments (some_lengthy_argument,
+ another_lengthy_argument,
+ and_another_one,
+ plus_one);
+ }
+ else
+ {
+ another_single_statement (arg1, arg2);
+ }
+```
+
+ ② if the condition is composed of many lines:
+
+```c
+ /* valid */
+ if (condition1 ||
+ (condition2 && condition3) ||
+ condition4 ||
+ (condition5 && (condition6 || condition7)))
+ {
+ a_single_statement ();
+ }
+```
+
+ ③ In the case of nested if's, the block should be placed on the outermost if:
+
+```c
+ /* valid */
+ if (condition)
+ {
+ if (another_condition)
+ single_statement ();
+ else
+ another_single_statement ();
+ }
+
+ /* invalid */
+ if (condition)
+ if (another_condition)
+ single_statement ();
+ else if (yet_another_condition)
+ another_single_statement ();
+```
+
+## Conditions
+
+Do not check boolean values for equality:
+
+```c
+ /* valid */
+ if (another_condition)
+ do_bar ();
+
+ /* invalid */
+ if (condition == TRUE)
+ do_foo ();
+```
+
+Even if C handles NULL equality like a boolean, be explicit:
+
+```c
+ /* valid */
+ if (some_pointer == NULL)
+ do_blah ();
+
+ /* invalid */
+ if (some_other_pointer)
+ do_blurp ();
+```
+
+When conditions split over multiple lines, the logical operators should always
+go at the end of the line. Align the same level boolean operators to show
+explicitly which are on the same level and which are not:
+
+```c
+ /* valid */
+ if (condition1 &&
+ condition2 &&
+ (condition3 || (condition4 && condition5)))
+ {
+ do_blah ();
+ }
+
+ /* invalid */
+ if (condition1
+ || condition2
+ || condition3)
+ {
+ do_foo ();
+ }
+```
+
+## Switch statement
+
+A `switch()` should open a block on a new indentation level, and each case
+should start on the same indentation level as the curly braces, with the
+case block on a new indentation level:
+
+```c
+ /* valid */
+ switch (condition)
+ {
+ case FOO:
+ do_foo ();
+ break;
+
+ case BAR:
+ do_bar ();
+ break;
+ }
+
+ /* invalid */
+ switch (condition) {
+ case FOO: do_foo (); break;
+ case BAR: do_bar (); break;
+ }
+
+ /* invalid */
+ switch (condition)
+ {
+ case FOO: do_foo ();
+ break;
+ case BAR: do_bar ();
+ break;
+ }
+
+ /* invalid */
+ switch (condition)
+ {
+ case FOO:
+ do_foo ();
+ break;
+ case BAR:
+ do_bar ();
+ break;
+ }
+```
+
+It is preferable, though not mandatory, to separate the various cases with
+a newline:
+
+```c
+ switch (condition)
+ {
+ case FOO:
+ do_foo ();
+ break;
+
+ case BAR:
+ do_bar ();
+ break;
+
+ default:
+ do_default ();
+ break;
+ }
+```
+
+If a case block needs to declare new variables, the same rules as the inner
+blocks (see above) apply; place the break statement outside of the inner block:
+
+```c
+ switch (condition)
+ {
+ case FOO:
+ {
+ int foo;
+
+ foo = do_foo ();
+ }
+ break;
+
+ ...
+ }
+```
+
+Do not add `default:` case if your `switch ()` is supposed to handle _all cases_.
+
+
+## Variables declaration and definition
+
+Place each variable on a new line. The variable name must be right-aligned,
+taking into account pointers:
+
+```c
+ /* valid */
+ int first = 42;
+ gboolean second = TRUE;
+ GimpObject *third = NULL;
+```
+
+Blocks of variable declaration/initialization should align the variable names,
+allowing quick skimming of the variable list.
+
+## Functions
+
+Function header has the return type on one line; the name starting in the first
+column of the following line. Prototype each parameter and place each on a
+new line.
+
+In function names, each word must be lowercase and separated by an underscore.
+
+In the function definition, place the return value on a separate line from the
+function name:
+
+```c
+void
+my_function (void)
+{
+}
+```
+
+The parameters list must be broken into a new line for each parameter, with the
+parameter names right-aligned, taking into account pointers:
+
+```c
+void
+my_function (some_type_t some_param,
+ another_type_t *a_pointer_param,
+ final_type_t final_param)
+{
+}
+```
+
+While curly braces for function definitions should rest on a new line they
+should not add an indentation level:
+
+```c
+/* valid */
+static void
+my_function (int parameter)
+{
+ do_my_things ();
+}
+```
+
+The alignment also holds when invoking a function:
+
+```c
+ align_function_arguments (first_argument,
+ second_argument,
+ third_argument);
+```
+
+If your function name is very long, it's always better to extract arguments into
+separate variables to improve readability:
+
+```c
+ /* valid */
+ first_a = argument_the_first;
+ second_a = argument_the_second;
+ a_very_long_function_name_with_long_arguments (first_a, second_a);
+```
+
+Keep the function name and the arguments on the same line. Otherwise, it will
+hurt readability.
+
+```c
+ /* invalid */
+ a_very_long_function_name_with_long_arguments
+ (argument_the_first, argument_the_second);
+```
+
+## Macros
+
+Try to avoid private macros unless strictly necessary. Remember to `#undef`
+them at the end of a block or a series of functions needing them.
+
+Use inline functions instead of private macro definitions.
+Do not use public macros unless they evaluate to a constant.
+
+## Includes
+
+GIMP source files should never include the global `gimp.h` header, but instead
+include the individual headers that are needed.
+
+Includes must be in the following order:
+
+ 0. `config.h` first;
+ 0. System and third-party headers;
+ 0. GIMP library headers (libgimp* headers);
+ 0. GIMP core/app headers that it needs including its own;
+
+Sort the includes within the blocks.
+
+
+```c
+/* valid */
+#include "config.h"
+
+#include <gegl.h>
+#include <gtk/gtk.h>
+
+#include "libgimpbase/gimpbase.h"
+#include "libgimpcolor/gimpcolor.h"
+
+#include "core/gimp.h"
+#include "core/gimpcontainer.h"
+
+#include "gimpcolorpanel.h"
+#include "gimpcontainerentry.h"
+```
+
+## Structures
+
+When declaring a structure type use newlines to separate logical sections:
+
+```c
+ /* preferred for new code*/
+ typedef struct
+ {
+ gint n_pages;
+ gint *pages;
+
+ gbool read_only;
+ } Pages;
+```
+
+## Memory management
+
+To dynamically allocate data on the heap, use `g_new()`. To allocate memory for
+multiple small data structures, `g_slice_new()`.
+
+When possible, all public structure types should be returned fully initialized,
+either explicitly for each member or by using g_new0() or g_slice_new0().
+
+As a general programming rule, it is better to allocate and free data on the
+same level. It is much easier to review code because you know that when you
+allocate something there, then you also free it there.
+
+```c
+GeglBuffer *buffer;
+void *p;
+
+*buffer = gegl_buffer_new (some, args);
+*p = g_new (something, n);
+
+/* do stuff */
+
+g_object_unref (buffer);
+g_free (p);
+```
+
+When a transfer of ownership is unavoidable make it clear in the function
+documentation.
+
+## API Documentation
+
+All public APIs must have proper gtk-doc comments. For functions, these should
+be placed in the source file directly above.
+These annotations are also relevant for [GObject
Introspection](https://gi.readthedocs.io/en/latest/annotations/giannotations.html) to generate bindings for
other languages.
+
+```c
+/* valid */
+/**
+ * gimp_object_set_name:
+ * @object: a #GimpObject
+ * @name: the @object's new name (transfer none)
+ *
+ * Sets the @object's name. Takes care of freeing the old name and
+ * emitting the ::name_changed signal if the old and new name differ.
+ **/
+void
+gimp_object_set_name (GimpObject *object,
+ const gchar *name)
+{
+
+ ...
+
+}
+```
+
+Doc comments for macros, function types, class structs, etc., should be placed
+next to the definitions, typically in headers.
+
+## Public API
+
+Avoid exporting variables as public API since this is cumbersome on some
+platforms. It is always preferable to add getters and setters instead.
+
+List all public functions alphabetically in the corresponding `.def` file.
+
+ - `app/gimpcore.def`
+ - `libgimp/gimp.def`
+ - `libgimpbase/gimpbase.def`
+ - etc
diff --git a/HACKING b/HACKING
index 6a76d7e5f0..01f7bcf9bf 100644
--- a/HACKING
+++ b/HACKING
@@ -131,48 +131,8 @@ Hackordnung
-----------
We encourage you to follow the GIMP coding style throughout the GIMP
project. For the core components (application and libs) this coding
-style is enforced. The GIMP coding style is defined as follows:
-
- * There's a single space between the function name and the opening
- paren.
-
- * Function names are lowercase, words separated by underscores.
-
- * Macros and enums are all uppercase, words separated by
- underscores.
-
- * Types are all words capitalized, no separators between words.
-
- * All functions in header files need to be prototyped.
-
- * Indentation rules are GNU coding style, in particular:
- - 2 characters indentation level
- - Do not use tabs (of course your editor can accept the TAB key
- as a command, typically to indent the current line properly
- or to add spaces at the cursor until the next multiple of 8
- columns, but it should not put TAB characters in the file).
- - When editing files that still have TABs in them, make sure your
- editor interprets the TABs correctly, that is, has tab stops
- at 8 column intervals.
- - Opening braces are on a new line and indented one level.
- - Function header have the return type on one line, the name
- starting in the first column of the following line. All
- parameters are prototyped and there's a new line for each.
-
- * Align relevant listing:
- - In declaration and definition of functions, each parameter
- should be on a new line and aligned with the first one.
- - In function calls, if the call is too long and spans on
- several lines, you should align the parameters with the first
- one.
- - Blocks of variable declaration/initialization should align the
- variable names, allowing quick skimming of the variable list.
- - Function names in blocks of function declarations should be
- aligned.
-
- * Avoid trailing whitespaces. Any editor should have a function to
- warn of trailing spaces/tabs. By default, git colorization also
- warns about trailing whitespaces.
+style is enforced. See separate CODING_STYLE.md for a detailed description
+of the source code style.
The source tree contains local config files which can be used to set the
right coding style in common editors: `.dir-locals.el` for Emacs,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]