6
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Uncrustifyのセッティング (4) アラインメント編 前編

Last updated at Posted at 2013-02-12

はじめに

次の設定の解説は空白設定にしようと思っていたが、項目が150項目もある。もはや、ちょちょっと解説するには苦痛なレベルだ。なので、空白設定はとりあえず飛ばそうと思う。

で、今回の設定の解説は、アラインメント設定についてだある。インデントとほとんど同じだけど、まぁもう少し細かな、行送りの時にはどうするとか、operatorキーワードに対してはどう位置揃えするとか、そういうことまで設定させてしまう。

あまりにも細かすぎて、ちょっとびっくりすると思うが、前回のインデントの設定も相当に細かいので、徐々に細かさに慣れてくる。しかし、uncrustifyというツールはパワフルだけど、誰も詳しく設定項目を解説してないのは何でだろうと思う。どうやら、UncrustifyXというツールが説明とかも付いているし、インタラクティブにUncrustifyの設定もできる便利ツールらしい。まだ試してはいないが、いつか試してみよう。

また、このアラインメントに関しては、「ラインスパン (Span)」、「カラム閾値 (Threshold)」、「カラムギャップ (Gap)」という3つのパラメータが登場する。Uncrustifyのドキュメントには、それぞれ以下のように説明されている。

  • ラインスパン

    ラインスパンというのは、アラインメントのための基準である。ラインスパンに行数を設定することで、前後何行分を見て位置揃えするかを判断する。これは、空行が間にあったり、カラムが非常に長いトークンが間にあったりする場合に、インテリジェントに位置揃えをしてくれる。単に、スパンとも呼ばれる。
  • カラム閾値

    カラム閾値というのは、アラインメントのための基準である。カラム閾値に桁数を設定することで、位置揃えされるトークンの左側にあるトークンのカラム差に対する制限幅である。単に、閾値とも呼ばれる。
  • カラムギャップ

    カラムギャップというのは、アラインメントのための基準である。位置揃えされたトークンの左側に付ける半角空白数である。単に、ギャップとも呼ばれる。

だいたい、それぞれの概念を例示してみる。

span_thresh_gap.cpp
// 4つの変数宣言の位置合わせについて考える。1つだけ、非常に変数型が長い。
{
   double d;
   int i;
   unsign long long ull;
   char c;
}

// ラインスパンが1行の場合、直前の行だけを見て位置揃えをする。
{
    double d;
    int    i;
    unsigned long long ull;
    char c;
}

// ラインスパンが2行の場合、前2行分を見て位置揃えをする。
{
    double d;
    int    i;
    unsigned long long ull;
    char   c;
}

// カラム閾値が2桁の場合、どの変数型(トークン)もカラム差が3文字以上なので、全く揃わない。
// (ラインスパンは1行)
{
    double d;
    int i;
    unsigned long long ull;
    char c;
}

// カラム閾値が3桁の場合、unsigned long long 以外のトークンのカラム差は3文字以内なので揃う。
// (ラインスパンは2行: そうでないと、int と char は行が離れていて、位置揃えの関係にならない。)
{
    double d;
    int    i;
    unsigned long long ull;
    char   c;
}

// カラムギャップは非常に簡単だ。
// ギャップを4桁に設定すれば、トークン (ここでは変数名) は少なくとも半角空白4個分のスペースを作る。
{
    double    d;
    int       i;
    char      c;
}

ただし、実際にUncrustifyのフォーマッタがこれらのアラインメントを実行するアルゴリズムはもう少し複雑だ。ユーザの期待した通りに整形してくれない場合もあるだろう。アラインメントの仕様については、リポジトリのdocumentation/配下にある"align-thresholds.txt"を参照してほしい。

アラインメント設定

なお、アラインメントオプションは、左側(行頭)にある半角空白やタブ文字はアライメント対象ではなく、それ以外の半角空白やタブ文字に対するオプションである。

項目 説明
align_keep_tabs インデントではないタブ文字を残すか { true, false }
align_with_tabs 整列位置合わせにタブ文字を利用するか { true, false }
align_on_tabstop 整列位置合わせで次のタブストップ位置にするか { true, false }
align_number_left 数値を左揃えにするかどうか (align_struct_init_spanと関連) { true, false }
align_func_params プロトタイプ宣言と関数定義で、変数定義の位置を揃えるかどうか { true, false }
align_same_func_call_params 同じ名前を持つシングルライン関数のパラメータの位置を揃えるかどうか (関数名はすでにそれぞれ位置合わせされていなければならない。) { true, false }
align_var_def_star_style 変数定義でのポインタの'*'の位置揃えの方法 { 0: 型の一部、1: 変数名の一部、2: ダングリング }
align_var_def_amp_style 変数定義での参照の'&'位置揃えの方法 { 0: 型の一部、1: 変数名の一部、2: ダングリング }
align_var_def_colon 構造体ビットフィールドの':'を位置揃えするかどうか { true, false }
align_var_def_attribute 変数名の後の属性を位置揃えするかどうか { true, false }
align_var_def_inline struct/enum/unionのメンバ変数定義を位置揃えするかどうか { true, false }
align_var_def_span 変数定義の位置揃えに対するラインスパン (0: 揃えない) { number }
align_var_def_thresh 変数定義の位置揃えのカラム閾値 (0: 制限無し) { number }
align_var_def_gap 変数定義の位置揃えのカラムギャップ { number }
align_assign_span 代入式の'='の位置揃えをするラインスパン (0: 揃えない) { number }
align_assign_thresh 代入式の'='の位置揃えをするカラム閾値 (0: 制限無し) { number }
align_enum_equ_span enumの'='の位置揃えをするラインスパン (0: 揃えない) { number }
align_enum_equ_thresh enumの'='の位置揃えをするカラム閾値 (0: 制限無し) { number }
align_var_struct_span struct/unionのメンバー定義の位置揃えをするラインスパン (0: 揃えない) { number }
align_var_struct_thresh struct/unionのメンバー定義の位置揃えをするカラム閾値 (0: 制限無し) { number }
align_var_struct_gap struct/unionのメンバー定義のカラムギャップ { number }
align_struct_init_span structのメンバ変数の指定初期化の位置揃えのラインスパン (0: 揃えない) { number }
align_typedef_gap typedefの型とシノニムの間の空白の最小数 { number }
align_typedef_span 一行typedefの位置揃えをするラインスパン (0: 揃えない) { number }
align_typedef_func typedefされた関数とその他typedefの位置揃えの方法 { 0: ミックスして位置を揃えない、1: 開丸括弧と型の位置を揃える、2: 関数の型名とその他の型名の位置を揃える }
align_typedef_star_style typedefの''の位置揃えの方法 { 0: typedef typeで揃える、1: ''を型名の一部とする、2: '*'を型名の一部としてダングリングする }
align_typedef_amp_style typedefの'&'の位置揃えの方法 { 0: typedef typeで揃える、1: '&'を型名の一部とする、2: '&'を型名の一部としてダングリングする }
align_right_cmt_span 行末コメントを位置揃えするラインスパン (0: 揃えない) { number }
align_right_cmt_mix If aligning comments, mix with comments after '}' and #endif with less than 3 spaces before the comment { true, false }
align_right_cmt_gap 行末コメントがこの桁数以上コードと離れている場合、位置揃えする (0: 揃えない) { number }
align_right_cmt_at_col 行末コメントの位置揃えするカラム位置 (嬉しい副産物 'pulls in' コメント) (0: 揃えない) { number }
align_func_proto_span プロトタイプ宣言の位置揃えのラインスパン (0: 揃えない) { number }
align_func_proto_gap プロトタイプ宣言の返値型と関数名の間のギャップカラム { number }
align_on_operator 'operator'キーワードでプロトタイプ宣言を位置揃えするかどうか { number }
align_mix_var_proto プロトタイプと変数宣言のミックス整形するかどうか (trueの場合、align_var_def_XXXオプションがalign_func_proto_XXXオプションの代わりに使用される。) { true, false }
align_single_line_func 一行関数を関数プロトタイプと同様に位置揃えするかどうか (align_func_proto_spanを使用) { true, false }
align_single_line_brace 一行関数のオープンブレースを位置揃えするかどうか (align_single_line_func=trueの場合のみ) (align_func_proto_spanを使用) { true, false }
align_single_line_brace_gap align_single_line_braceに対するギャップ { number }
align_nl_cont バックスラッシュ-改行で囲われた複数行マクロを位置揃えするかどうか (ただし、マクロが複数行コメントを内包している場合、うまく動かない) { true, false }
align_pp_define_span プリプロセッサ定義のボディの位置揃えのスパン (0: 揃えない) { number }
align_pp_define_gap プリプロセッサ定義のラベルと値の間の空白の最小幅 { number }
align_pp_define_together マクロ関数とマクロ変数を一緒に位置揃えするかどうか { true, false }
align_left_shift '<<'で開始する行を前の行の'<<'の位置に揃えるかどうか (デフォルト: true) { true, false }
align_oc_msg_spec_span Objective-Cのメッセージ仕様宣言のスパン (0: 揃えない) { number }
align_oc_msg_colon_span Objective-Cのメッセージコールにおけるパラメータ':'の位置揃えのスパン (0: 揃えない) { number }
align_oc_msg_colon_first trueの場合、最初のパラメータの位置に後続パラメータの位置を揃える (メッセージが短くとも) { true, false }
align_oc_decl_colon Objective-Cの'+'もしくは'-'宣言行のパラメータを':'で位置揃えするかどうか { true, false }

僕の設定

align.cfg
align_keep_tabs                          = false
align_with_tabs                          = false
align_on_tabstop                         = false
align_number_left                        = false
align_func_params                        = true
align_same_func_call_params              = false
align_var_def_star_style                 = 0
align_var_def_amp_style                  = 0
align_var_def_colon                      = true
align_var_def_attribute                  = true
align_var_def_inline                     = true
align_var_def_span                       = 2
align_var_def_thresh                     = 6
align_var_def_gap                        = 0
align_assign_span                        = 2
align_assign_thresh                      = 6
align_enum_equ_span                      = 2
align_enum_equ_thresh                    = 6
align_var_struct_span                    = 2
align_var_struct_thresh                  = 6
align_var_struct_gap                     = 0
align_struct_init_span                   = 1
align_typedef_gap                        = 0
align_typedef_span                       = 2
align_typedef_func                       = 1
align_typedef_star_style                 = 0
align_typedef_amp_style                  = 0
align_right_cmt_span                     = 4
align_right_cmt_mix                      = false
align_right_cmt_gap                      = 1
align_right_cmt_at_col                   = 0
align_func_proto_span                    = 2
align_func_proto_gap                     = 0
align_on_operator                        = true
align_mix_var_proto                      = false
align_single_line_func                   = true
align_single_line_brace                  = true
align_single_line_brace_gap              = 0
align_nl_cont                            = true
align_pp_define_span                     = 2
align_pp_define_gap                      = 0
align_pp_define_together                 = true
align_left_shift                         = true
align_oc_msg_spec_span                   = 0
align_oc_msg_colon_span                  = 0
align_oc_msg_colon_first                 = false
align_oc_decl_colon                      = false

ALIGN_KEEP_TABS

align_keep_tabs.cpp
// 整形前
int var,--->var2;

// align_keep_tabs = true
// タブ文字は残る。
int var,--->var2;

// align_keep_tabs = false
// タブ文字は半角空白4個に展開される。
// この半角空白の数は、input_tab_sizeとoutput_tab_sizeに依存する。
int var,....var2;

ALIGN_WITH_TABS

align_with_tabs.cpp
// 整形前
int foo = 1;
int bar = 1;
int foobar = 2;
int foobarfoobar = 4;

// align_with_tabs = true
// '='の位置合わせでは、このようにタブ文字が使われる。(output_tab_size = 4)
int foo>--->---> = 1;
int bar>--->---> = 1;
int foobar->---> = 2;
int foobarfoobar = 4;

// align_with_tabs = false
// 半角空白のみで位置が揃えられる。
int foo......... = 1;
int bar......... = 1;
int foobar...... = 2;
int foobarfoobar = 4;

ALIGN_ON_TABSTOP

align_on_tabstop.cpp
// 整形前
int foo = 1;
int bar = 1;
int foobar = 2;
int foobarfoobar = 4;

// align_on_tabstop = true
// '='の位置合わせでは、次のタブ位置で揃えられる。(output_tab_size = 4)
int foo             = 1;
int bar             = 1;
int foobar          = 2;
int foobarfoobar    = 4;

// align_on_tabstop = false
// 一番短く揃えられる位置で揃えられる。
int foo          = 1;
int bar          = 1;
int foobar       = 2;
int foobarfoobar = 4;

ALIGN_NUMBER_LEFT

align_number_left
// align_number_left = true (&& align_struct_init_span = 10)
// 構造体フィールドの初期化の数値リテラルが右寄せになる。
struct Foo foo = {
    .x =   1,
    .y =  23,
    .z = 456,
};

ALIGN_FUNC_PARAMS

align_func_params.cpp
// align_func_params = true
// 関数定義やプロトタイプ宣言の引数リストの型と変数名の間が位置揃えされる。
void func(
    int   param1,
    short param2,
    long  param3);

// align_func_params = false
// 関数定義やプロトタイプ宣言の引数リストの型と変数名の間は揃えられない。(何しない)
void func(
    int param1,
    short param2,
    long param3);

ALIGN_SAME_FUNC_CALL_PARAMS

align_same_func_call_params
// align_same_func_call_params = true
// 同じ関数呼び出すが複数行並んでいた場合、引数の位置を揃える。
void function(void)
{
    foo(abc,  def,  xyz);
    foo(abcd, efgh, ijkl);
}

// align_same_func_call_params = false
// 同じ関数呼び出しが並んでいても、引数の位置は自動的には揃わない。(何もしない)
void function(void)
{
    foo(abc, def, xyz);
    foo(abcd, efgh, ijkl);
}

ALIGN_VAR_DEF_STAR_STYLE

align_var_def_star_style.cpp
// align_var_def_star_style = 0
// 変数宣言におけるポインタの'*'を変数の型に付ける。
    int     integer;
    int*    i_ptr;
    char*   c_ptr;
    double* d_ptr;
    float*  f_ptr;

// align_var_def_star_style = 1
// 変数宣言におけるポインタの'*'を変数名の先頭に付け、'*'は非ポインタ型の変数名の先頭位置と位置揃えする。
    int    integer;
    int    *i_ptr;
    char   *c_ptr;
    double *d_ptr;
    float  *f_ptr;

// align_var_def_star_style = 2
// 変数宣言におけるポインタの'*'を変数名の先頭に付ける。変数名の先頭で位置揃えを行う。'*'はダングリングさせる。
    int     integer;
    int    *i_ptr;
    char   *c_ptr;
    double *d_ptr;
    float  *f_ptr;

ALIGN_VAR_DEF_AMP_STYLE

align_var_def_amp_style.cpp
// align_var_def_amp_style = 0
// 変数宣言における参照の'&'を変数の型に付ける。
    int     integer;
    int&    i_ptr;
    char&   c_ptr;
    double& d_ptr;
    float&  f_ptr;

// align_var_def_amp_style = 1
// 変数宣言における参照の'&'を変数名の先頭に付け、'&'は非参照型の変数名の先頭位置と位置揃えする。
    int    integer;
    int    &i_ptr;
    char   &c_ptr;
    double &d_ptr;
    float  &f_ptr;

// align_var_def_amp_style = 2
// 変数宣言における参照の'&'を変数名の先頭に付ける。変数名の先頭で位置揃えを行う。'&'はダングリングさせる。
    int     integer;
    int    &i_ptr;
    char   &c_ptr;
    double &d_ptr;
    float  &f_ptr;

ALIGN_VAR_DEF_COLON

align_var_def_colon.cpp
// align_var_def_colon = true
// 構造体のビットフィールドの':'の位置を揃える。
struct Bitfields
{
    unsigned int bit1     : 1;
    unsigned int bit2_8   : 7;
    unsigned int bit9_16  : 8;
    unsigned int bit17_32 : 16;
};

// align_var_def_colon = false
// ビットフィールドを揃えない。(何もしない)
struct Bitfields
{
    unsigned int bit1 : 1;
    unsigned int bit2_8 : 7;
    unsigned int bit9_16 : 8;
    unsigned int bit17_32 : 16;
};

ALIGN_VAR_DEF_ATTRIBUTE

align_var_def_attribute.cpp
// align_var_def_attribute = true
// 変数属性の'__attribute__'の位置を合わせる。
unsigned char original[128] __attribute__(aligned(128));
unsigned char copy[128]     __attribute__(aligned(128));
unsigned char result[128]   __attribute__(aligned(128));

// align_var_def_attribute = false
// 変数属性の'__attribute__'の位置を合わせない。(何もしない)
unsigned char original[128] __attribute__(aligned(128));
unsigned char copy[128] __attribute__(aligned(128));
unsigned char result[128] __attribute__(aligned(128));

ALIGN_VAR_DEF_INLINE

align_var_def_inline.cpp
// align_var_def_inline = true
// 構造体のメンバ変数の宣言(型名とメンバ変数名)の位置を揃える。
struct Foo
{
    int   bar1;
    short bar2;
}

// align_var_def_inline = false
// 構造体のメンバ変数の宣言(型名とメンバ変数名)の位置を揃えない。(何もしない)
struct Foo
{
    int bar1;
    short bar2;
}

ALIGN_VAR_DEF_SPAN

align_var_def_span.cpp
// align_var_def_span = 0
// 変数定義の位置揃えは行わない。
{
    int a;
    char bbb;
    long ccc;

    float dddd;
    double eeeeee;


    unsigned int ff;
    unsigned char gggg;
}

// align_var_def_span = 1;
// 行が連続した変数定義の範囲だけ一緒に位置揃えを行う。
{
    int  a;                 // aligned 1
    char bbb;               // aligned 1
    long ccc;               // aligned 1

    float  dddd;            // aligned 2
    double eeeeee;          // aligned 2


    unsigned int  ff;       // aligned 3
    unsigned char gggg;     // aligned 3
}

// align_var_def_span = 2;
// 空行が1行開いている変数定義でも一緒に位置揃えを行う。
{
    int    a;               // aligned 1
    char   bbb;             // aligned 1
    long   ccc;             // aligned 1

    float  dddd;            // aligned 1
    double eeeeee;          // aligned 1


    unsigned int  ff;       // aligned 2
    unsigned char gggg;     // aligned 2
}

// align_var_def_span = 3   ;
// 空行が2行開いている変数定義でも一緒に位置揃えを行う。
{
    int           a;        // aligned with all
    char          bbb;      // aligned with all
    long          ccc;      // aligned with all

    float         dddd;     // aligned with all
    double        eeeeee;   // aligned with all


    unsigned int  ff;       // aligned with all
    unsigned char gggg;     // aligned with all
}

ALIGN_VAR_DEF_THRESH

align_var_def_thresh.cpp
// align_var_def_thresh = 3
// double(6文字)とint(3文字)のカラム差(3文字)は位置揃えされるが、
// long(4文字)とunsigned char(13文字)のカラム差(9文字)は位置揃えされない。
{
    float  dddd;
    double eeeeee;
    int    a;
    char   bbb;
    long   ccc;
    unsigned int  ff;
    unsigned char gggg;
}

// align_var_def_thresh = 2
// floatとdouble、intとcharとlong、unsigned intとunsigned charは揃えられるが、
// doubleとint、longとunsigned charは位置揃えされない。
{
    float  dddd;
    double eeeeee;
    int  a;
    char bbb;
    long ccc;
    unsigned int  ff;
    unsigned char gggg;
}

ALIGN_VAR_DEF_GAP

align_var_def_gap.cpp
// align_var_def_gap = 0 (align_var_def_gap = 1も同じ)
// 変数の型と変数名の間に半角空白1文字分の余白を空ける。
{
    float         dddd;
    double        eeeeee;
    int           a;
    char          bbb;
    long          ccc;
    unsigned int  ff;
    unsigned char gggg;
}

// align_var_def_gap = 4
// 変数の型と変数名の間を最小で半角空白4文字分を確保して位置揃えする。
{
    float        ....dddd;
    double       ....eeeeee;
    int          ....a;
    char         ....bbb;
    long         ....ccc;
    unsigned int ....ff;
    unsigned char....gggg;
}
6
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?