# Contributing to wayvnc

## LLM/AI

It's OK to use an LLM to generate code, but you need to fully understand the
generated code in detail and as a whole. Beware that LLMs often present
falsehoods as truths. To counter this, you need to do your own research to
verify that what the LLM gives you is correct.

For example, if you are implementing a feature that is described on the
[RFB specification](https://github.com/rfbproto/rfbproto/blob/master/rfbproto.rst),
you need to read and understand the relevant sections of the specification. You
can use an LLM to help you find the relevant sections, but do not rely on
summaries alone.

## Commit Messages

Please, try to write good commit messages. Do your best to follow these 7 rules,
borrowed from [Chris Beams](https://chris.beams.io/posts/git-commit/), plus 1
extra rule:

 1. Separate subject from body with a blank line
 2. Limit the subject line to 50 characters
 3. Capitalize the subject line
 4. Do not end the subject line with a period
 5. Use the imperative mood in the subject line
 6. Wrap the body at 72 characters
 7. Use the body to explain what and why vs. how
 8. (Extra) Prefix the subject line with the component that's modified

If you wish to know why we follow these rules, please read Chris Beams' blog
entry, linked above.

Rule number 8 allows us to quickly gauge if a given commit is relevant to what
we're looking for when skimming the log. It adds consistency and simplifies the
message. For example
```
ctl-client: Print trailing newline for events
```
is better than
```
Print trailing newline for events in ctl-client
```

**Example:**

```
ctl-client: Print trailing newline for events

If someone wants to parse this instead of using jq, a trailing
newline delimits the end of the event.
```

## Style

This project follows the the
[Linux kernel's style guide](https://www.kernel.org/doc/html/latest/process/coding-style.html#codingstyle)
as far as coding style is concerned, with the following exceptions:

 * When declaring pointer variables, the asterisk (`*`) is placed on the left
   with the type rather than the variable name. Declaring multiple variables in
   the same line is not allowed.
 * Wrapped argument lists should not be aligned. Use two tabs instead. There is
   a lot of code that uses aligned argument lists in the project, but I have
   come to the conclusion that these alignments are not very nice to maintain.

### Summary & Examples:

In case you aren't familiar with Linux's coding style, here is a short summary
and some examples of acceptable formatting:

 * Use tabs for indenting.
 * We do not align code (mostly), but when we do, we use spaces rather than
   tabs. This rule is not according to the Linux style guide.
 * The preferred limit on the length of a single line is 80 columns.
 * User-visible string such as log messages must not be split up.
 * Use space after the following keywords: `if`, `switch`, `case`, `for`, `do`,
   `while`.
 * Do **not** use space after others such as: `sizeof`, `typeof`, `alignof`
   or `__attribute__`.
 * Do **not** use typedefs.
 * It is allowed to use typedefs for function pointers. This rule is not
   according to the Linux style guide.

#### Functions

```
static int do_something(int number, const char* text)
{
	body of function
}
```

#### `if`

```
	// Single statement
	if (condition)
		do_this();

	// Multiple statements
	if (condition) {
		do_this(2, "41");
		do_that();
	}

	// Single statement if/else
	if (condition)
		do_this();
	else
		do_that();

	// Multi-statement if/else
	if (condition) {
		do_this();
		do_that();
	} else {
		otherwise();
	}
```

#### `switch`

```
	switch (value) {
	case 3:
		printf("three!\n");
		break;
	case 5:
		printf("five!\n");
		break;
	case 42:
		printf("the answer to life, the universe and everything: ");
		// fallthrough
	default:
		printf("%d\n", value);
		break;
	}
```

#### Arithmetic

```
	int a = b * c + 5;
```

#### Pointers

```
	char* some_text = "some text";
	char* just_text = text + 5;
	char t = *just_text;
	char e = just_text[1];
```

## Testing

### Unit Tests

wayvnc has a small but growing set of unit tests, which are run on every GitHub
PR. To run them locally, do the following:
```bash
meson test -C build
```

### Integration Tests

There are also a handful of integration tests which also run on every PR.  Read
the [integration tests documentation](test/integration/README.md) for more
details, but to run them locally:
```
./test/integration/integration.sh
```

### Valgrind

There is a helper script in [util/valgrind.sh](util/valgrind.sh) to aid in
memory profiling of wayvnc and wayvncctl. This can help find and eliminate
memory leaks.

### Automated Tests

We run a set of tests on every PR, in three different environments.

Each run ensures that the proposed code change:
1. Builds successfully
2. Passes all unit tests
3. Passes all integration tests

And does so in 3 different environments:
- Ubuntu as a [github action](.github/workflows/build.yml)
- Arch Linux as a [sourcehut build](.builds/archlinux.yml)
- FreeBSD as a [sourcehut build](.builds/freebsd.yaml)

## No Brown M&Ms

All pull requests must contain the following sentence in the description:
I have read and understood CONTRIBUTING.md.
