Editor Settings for OpenAFS Development

The OpenAFS code base uses a mix of tabs and spaces for leading whitespace. This can make editing code difficult unless your editor is properly configured (and is not great even when your editor is configured correctly). The indentation size is 4 columns and every 8 space characters are replaced with a single tab character. That is, the tab stop is 8 but the indentation width is 4.

indent

The GNU indent program should be used to format new source files (and new functions within a file) so they are consistent with the current code base. The following indent options should be used:

$ indent -npro -nbad -bap -nbc -bbo -br -ce -cdw -brs -ncdb -cp1 \
  -ncs -di2 -ndj -nfc1 -nfca -i4 -lp -npcs -nprs -psl -sc -nsob -ts8 \
  <filename>

You can set these options to be specified automatically by creating a file called $HOME/.indent.pro:

$ cat $HOME/.indent.pro
-npro -nbad -bap -nbc -bbo -br -ce -cdw -brs -ncdb -cp1 -ncs -di2 -ndj -nfc1 -nfca -i4 -lp -npcs -nprs -psl -sc -nsob -ts8

Be careful to not introduce whitespace changes with indent on existing code, unless your commit is specifically, and only, cleaning up whitespace.

vim

The following are suggested vim settings to use when editing OpenAFS source files. These can be placed in your $HOME/.vimrc file, or in a separate file, and included in your vim settings with the :source command.

" Tab settings for OpenAFS indentation.
set noexpandtab
set tabstop=8
set softtabstop=4
set shiftwidth=4

" Enable syntax highlighting.
" Show trailing spaces and spaces before tabs as errors.
" Show leading whitespace errors.
syntax on
let c_space_errors=1
autocmd Syntax * syntax match cError /^ \{8,\}\|\t\+\zs \{8,\}\ze/

" Show tabs as visible characters.
" Run :set list! to toggle.
set list
set listchars=tab:>-

" Show a vertical ruler in column 80.
" Run :set cc= to remove the ruler and :set cc=80 to show the ruler.
highlight ColorColumn ctermbg=lightgrey guibg=lightgrey
set colorcolumn=80

You may want to enable the above settings only when editing OpenAFS source files (for example, to avoid adding tabs in code in other projects). There are several vim plugins and methods available to support project specific settings. These can be useful in general if you are using vim to work on different projects. For more info, see

VS Code

VS Code (code) is a popular programming editor and can be used to edit OpenAFS source and visually debug userspace programs. Unfortunately, support for mixed tab and space indentation is currently not supported in VS Code, but work is in progress to improve the situation. See Issue 5394.

Add the following settings in the .vscode/settings.json file in the top level project directory:

{
    "editor.formatOnSave": false,
    "editor.tabSize": 8,
    "editor.insertSpaces": false,
    "editor.detectIndentation": false,
    "editor.renderWhitespace": "all",
    "editor.rulers": [80],
    "files.trimTrailingWhitespace": false
}

Be sure to specify --exclude .vscode when running git clean, or git will delete your vscode settings. You probably will want to create a git alias for clean with this exclude option.

Sublime Text

Sublime Text is another popular editor and can be used to edit OpenAFS source. As with VS Code the support for mixed tab and space indentation is not supported natively, however there is a plugin, Smart Indent that adds the necessary support.

Using the following settings for editing OpenAFS:

Create a project for openafs, and add the following settings for the project (Project->Edit Project):

{
    "settings":
        {
            "tab_size": 4,
            "translate_tabs_to_spaces": false,
            "use_tab_stops": true,
            "trim_trailing_white_space_on_save": "none",
            "trim_only_modified_white_space": true,
            "rulers":
            [
                80, 120
            ]
        }
}

Install the Smart Indent package and use the following package settings (Preferences->Package Settings->Smart Indent->Settings - User):

{
    "extensions": [".cpp", ".hpp", ".c", ".h", ".C", ".H",".xg",".m4"],
    "translate_spaces_to_tabs": true,
    "indent_size": 4,
    "tab_size": 8
}

Sublime Text Syntax highlighting

To flag whitespace problems, a syntax extension can be defined. In the Sublime Text config directory (e.g. for Linux ~/.config/sublime-text/Packages/User) add the following 2 files (the syntax extension relies on the "invalid" scope from the color theme):

C_afs.sublime-syntax

%YAML 1.2
---
# http://www.sublimetext.com/docs/3/syntax.html

# Extends C syntax to hightlight leading and trailing whitespace errors
# per AFS coding standards

name: C_afs
file_extensions:
  - c
  - h
first_line_match: "-[*]-( Mode:)? C -[*]-"
scope: source.c
extends: Packages/C++/C.sublime-syntax

contexts:
  comments:
    - meta_append: true
    - match: '[ \t]+$'
      scope: invalid.illegal.trailing-whitespaces-comment.c
    - match: '[ \t]* +\t'
      scope: invalid.illegal.spacesbefore-tabs-comment.c
    - match: '[ \t]* {8}'
      scope: invalid.illegal.spacesimbedded-tabs-comment.c

# Can't directly extend the string rule,
# Instead extend an existing rule that is called from within a string.
  string_escaped_char:
    - meta_prepend: true
    - match: '[ \t]+$'
      scope: invalid.illegal.trailing-whitespaces-strings.c
    - match: '\t'
      scope: invalid.illegal.embedded-tabs-strings.c

  preprocessor-line-continuation:
    - meta_prepend: true
    - match: '[ \t]+$'
      scope: invalid.illegal.trailing-whitespace-preprocessor.c
    - match: '[ \t]* +\t'
      scope: invalid.illegal.spacesbefore-tabs-preprocessor.c
    - match: '[ \t]* {8}'
      scope: invalid.illegal.spacesimbedded-tabs-preprocessor.c

  preprocessor-comments:
    - meta_prepend: true
    - match: '[ \t]+$'
      scope: invalid.illegal.trailing-whitespace-preproc-comment.c
    - match: '[ \t]* +\t'
      scope: invalid.illegal.spacesbefore-tabs-preproc-comment.c
    - match: '[ \t]* {8}'
      scope: invalid.illegal.spacesimbedded-tabs-preproc-comment.c
  preprocessor-if-branch-global:
    - meta_prepend: true
    - match: '^[ \t]*#[ ]*(if|elif|ifdef|ifndef)[ ]*([\t][ \t]*)[^ \t]'
      captures:
        2: invalid.illegal.imbeddedtabs.c

  early-expressions:
    - meta_prepend: true
    - match: '[ \t]+$'
      scope: invalid.illegal.trailing-whitespace.c
    - match: '[ \t]* +\t'
      scope: invalid.illegal.spacesbefore-tabs.c
    - match: '[ \t]* {8}'
      scope: invalid.illegal.spacesimbedded-tabs.c
    - match: '^[ \t]*#[ ]*[\t][ \t]*[^ \t]'
      scope: invalid.illegal.imbeddedtabs.c
    - match: '^[ \t]*#[ ]*(if|elif|ifdef|ifndef|define|undef)[ ]*([\t][ \t]*)[^ \t]'
      captures:
        2: invalid.illegal.imbeddedtabs.c

C_afs.sublime-settings

{
    "extensions":
    [
        "c","h"
    ],
}