Contribution Guide

Tests

Run $ make at the root of Citre project to run all the tests.

We've setup CI to run the tests automatically on various versions of Emacs. The CI is triggered on pull requests, or on pushes to the master/develop branch.

Add a test case

Please refer to existing tests under tests/.

If you want to add a test case that doesn't use a tags file, see the test core-parse-pattern.

If you want to add a test case that needs tags file(s), see the test core-main-apis (use 1 tags file) and core-locate-tag (use multiple tags file). For such test cases, you need to:

I (@AmaiKinono) should regularly update u-ctags on my machine and run $ make test-tags to update all the tags files. If a new version of u-ctags generates a tags file differently and breaks a test case, I should fix it.

Style

Code or shell commands in the docs may contain long lines. In these cases, break the line by a \.

Don't worry to much as we also have style tests when you run $ make and on the CI.

Misc

The develop branch is there only for running tests on all versions of Emacs. Once it's passed, we rebase the master branch to it. So the master branch is really not a "stable branch".

Working with files

Currently file-related code is still a bit entangled in Citre, though I've put much effort clear it up.

Let's start with basic concepts:

/ssh:user@host:/path/to/file

These terms are orthogonal, e.g., you can have "remote canonical path" or "local absolute path".

Here are some guidelines when working with filenames.

When to use canonical/full/absolute path

When the filename is associated with additional info, it's better to use canonical path to store them.

For example, in Citre, tags files come with additional info like its root directory, etc. These are stored in a hash table, where the keys are canonical paths of the tags files, and values are the additiona info.

That said, when exposing APIs to upper components, it's often be better to ask for absolute path, and canonicalize it by file-truename, so upper components can path canonical or non-canonical paths. Ideally, all APIs in citre-core.el and citre-util.el should be designed like this.

When generating a tags file, if you feed a full path that contains symlink to Ctags, the tags file will record it as it is. Then, when filtering the input field with a canonical path, it's a problem how to get that full path with that symlink. We really can't do anything here, luckily this should only be a corner case. Currently when filtering the input field using buffer-file-name, Citre uses the full path, and not canonicalize it, hoping the user are visiting the file through the same symlink.

When to use local/remote path

Whenever you use Elisp to access a file, use local path for local files, and remote path for remote files. It's easy to understand.

Troubles happens in 2 situations:

Others

expand-file-name says it will canonicalize the file name. From what I've seen, it doesn't resolve the symlinks. Maybe Emacs defines "canonical path" differently with us. When you need to resolve symlinks, use file-truename.

Some functions, like file-name-absolute-p, works differently on different platforms. Trouble happens when you visit a Unix remote machine on Windows, and you use local path on that remote machine (e.g. it's come from the tags file), these functions treat them as Windows paths. When this is a problem, we use the os additional info field of the tags file to know the OS of the remote machine, and do things manually.

The default file-exists-p doesn't differ directories and files. If you know you want a directory or a file, use citre-non-dir-file-exists-p and citre-dir-exists-p instead.