# Style Guide

We mostly use the [GTK style
guide](https://gitlab.gnome.org/GNOME/gtk/-/blob/main/docs/CODING-STYLE.md)
by default. Some exceptions are listed below.

We also target the same [toolchain
requirements](https://github.com/GNOME/glib/blob/main/docs/toolchain-requirements.md)
as glib.

## General Style hints
* Overally, we prefer code legibility over brevity or cleverness.
* Declare variables at the top of the scope, in order they're
  used. Mid-function declarations are discouraged.
* Always use `g_autofree` and `g_autoptr` where possible. Do one per
  line, and make sure they're initialized to NULL. Asan will complain
  if they aren't.
  ```C
  g_autofree gchar *str = NULL; // This is fine
  g_autofree gchar *str2; // Not initialized to NULL. This is wrong
  ```
* Include the minimum number of header files, and list them in
  alphabetical order.
* Use spaces instead of tabs. Run this command to check for
  any occurances of tabs:
  ```bash
  $ grep -r $'\t'
  ```
* Use C-style comments for explanitary notes. `/* . . . */` instead of
  C++-style `//`. The latter are reserved for transient issues.
   * Example: If you have a debugging print-statement that's often
     used, feel free to use `//`. Ex:
     ```C
       //puzzle_set_model_print (self);
     ```
   * Example 2: For things that are broken and need to be fixed, we
     sometimes temporarily will use `//` as well.
* We follow the GTK brace convention with if statements, though are a
  bit more liberal in using braces:
  ```C
  if (condition)
    do_one_thing ();

  if (condition)
    do_one_thing ();
  else
    do_another_thing ();

  if (condition)
    {
      do_one_thing ();
      do_another_thing ();
    }
  else
    {
      // Different than GTK convention
      do_a_third_thing ();
    }
  ```
  That last example is a little different than the GTK style-guide,
  which might omit the last braces.

## FIXME messages

If you're going to leave a FIXME in the code, please put the domain in
parens. That make it easy to grep for all common areas that may need
fixing. As an example:

```C
/* FIXME(css): This color is hardcoded instead of css based. See bug #xxx */
```

We don't use TODO or have a well maintained TODO.md file. Please file
bugs for all other issues.

Common FIXME domains:
* *error*: an unhandled error, that probably needs a better message to
  the user than a g_warning.
* *refactor*: clean up an egregiously messy area of code
* *optimization*: a chunk of code is unnecessarily slow/big
* *css*: Something that should be moved to be a CSS setting
* *gtk/adwaita/libfoo*: Work around for an issue in a
  dependency. Often includes the version number it was fixed or
  introduced.
* *magichars*: A hardcoded constant in the code, that should be
  centralized or made configurable
* *mystery*: Something we don't understand in the code and couldn't
  figure out.

## File order

Within a file, we use the following section order. Keep two newlines
between each section, and one newline within each section:

* License
* Includes
* Local #defines and enums. Global tables
* Object properties and signals
* Object structs
* Local headers
* G_DEFINE_TYPE()
* Object methods, with small helper functions immediately above the caller
* Local methods, in order they're called
* Public methods
* Global helper functions

Note, this is mostly aspirational, and has settled over time. Very few
files follow this to the letter. We fix them as we see them.

## Trailing whitespace

We kill all whitespace after any line. To check if the changes in your
current branch have any trailing whitespace, run this command:
```bash
$ git diff --check master
```
If your branch isn't based on `master`, then replace `master` with
the actual base branch or commit.

To check for all trailing whitespace in the codebase (not just
those from your current branch), run this command:
```bash
# Do a diff check against the first ever commit,
# and exclude any dirs that we expect to contain trailing whitespace.

# NOTE: You must run this command in the root crosswords directory,
# in order for the exclusions to work.

$ git diff --check 460554e5 -- ':(exclude)word-lists/' ':(exclude)puzzle-sets/'
```

Please include a trailing newline at the end of the file.
