Code formatting¶
Some projects will want to have open curly-brackets on new lines (see Allman indenting style), other will prefer to have the open bracket on the same line as the function/control-statement/… (see K&R indenting style, Java coding style…). We can also choose whether one space shall be inserted before opening braces, and so on.
Of course we could apply reformatting tools (like clang-format) on demand, but then we’d need to identify a set of different tools dedicated to different languages. The day code formatting is handled by Language Server Protocol, we would have access to a simple and extensible solution. In the mean time, here is lh-style.
lh-style doesn’t do any replacement by itself on snippets or abbreviations. It is expected to be used by snippet plugins or from abbreviation definitions. So far, only mu-template and lh-cpp exploit this feature.
Different people will need to do different things:
- Plugin maintainers will use the dedicated API to reformat on-the-fly the code they generate.
- End-users will specify the coding style used on their project(s):
- either by specifying a set of independent styles on different topics (families) (
:UseStyle
,.editorconfig
,.clang-format
), - or by being extremely precise (
:AddStyle
).
- either by specifying a set of independent styles on different topics (families) (
Style families¶
Families already implemented¶
At this time, the following style families are implemented:
- EditorConfig styles:
curly_bracket_next_line
= [yes
,no
] //true,
false,
0,
1
.indent_brace_style
= [0tbs
,1tbs
,allman
,bsd_knf
,gnu
,horstmann
,java
,K&R
,linux_kernel
,lisp
,none
,pico
,ratliff
,stroustrup
,whitesmiths
]spaces_around_brackets
= [inside
,outside
,both
,none
]
- Clang-Format styles:
breakbeforebraces
= [allman
,attach
,gnu
,linux
,none
,stroustrup
]spacesbeforetrailingcomments
= [\n
, positive number of spaces]spacesbeforeparens
= [none
,never
,always
,control-statements
]spacesinemptyparentheses
= [yes
,no
] //true,
false,
0,
1
.spacesinparentheses
= [yes
,no
] //true,
false,
0,
1
.
Styles can easilly be added in {&rtp}/autoload/lh/style/
.
If you want more precise control, without family management, you can use :AddStyle
instead.
:UseStyle style-family=value [-buffer] [-ft[=ft]] [-prio=prio]
¶
Given style families, :UseStyle
can be used to specify which particular style shall be used when generating
code.
For instance,
:UseStyle breakbeforebraces=Allman -ft=c
:UseStyle spacesbeforeparens=control-statements -ft=c
:UseStyle spacesinparentheses=no
will tune snippets/abbreviations to follow Allman indenting style, and to add a space before control-statement parentheses, and to never insert a space inside parentheses.
Note
Some families are incompatible with other families. It happens quickly when we mix overlapping families from different origins.
:UseStyle
options¶
style-family=value
specifies, given a style family, what choice has been made.-buffer
defines this association only for the current buffer. This option is meant to be used with plugins like local_vimrc.-ft[=ft]
defines this association only for the specified filetype. Whenft
is not specified, it applies only to the current filetype. This option is meant to be used in .vimrc, in the global zone of filetype-plugins or possibly in local_vimrcs (when combined with-buffer
).-prio=prio
Sets a priority that’ll be used to determine which key is matching the text to enhance. By default all styles have a priority of 1. The typical application is to have template expander ignore single curly brackets.
Note
Local configuration (with -buffer
) have the priority over filetype specialized configuration (with -ft
).
.editorconfig
¶
lh-style registers a hook to editorconfig-vim in order to extract
style choices expressed in any .editorconfig
file that applies.
The syntax would be:
[*]
indent_brace_style=Allman
In every buffer where EditorConfig applies its settings, it will be translated into:
:UseStyle -b indent_brace_style=allman
.clang-format
¶
The idea is the same: to detect automatically a .clang-format
configuration file in project root directory and apply
the styles supported by lh-style.
Warning
At this time, this feature isn’t implemented yet.
Extending the families¶
New style families can be defined (and even contributed back – as soon as I write the contributing guide…). The following procedure has to be respected:
- Create a new autoload plugin named
rtp/autoload/lh/style/family-name.vim
- Define the following (required) functions:
lh#style#family-name#_known_list()
which will be used by command-line completion
lh#style#family-name#use(styles, value [, options])
which defines the chosen style.The typical content of this function is the following:
function! lh#style#{family-name}#use(styles, value, ...) abort let input_options = get(a:, 1, {}) let [options, local_global, prio, ft] = lh#style#_prepare_options_for_add_style(input_options) " I usually use a `lh#style#{family-name}#__new()` function for this purpose. let s:crt_style = lh#style#define_group('some.unique.family.id', name, local_global, ft) " Then we dispatch the a:value option to decide how the text should be displayed if a:value =~? value_pattern1 call s:crt_style.add(regex1, repl1, prio) elseif a:value =~? value_pattern2 call s:crt_style.add(regex2, repl2, prio) else call s:crt_style.add(regex3, repl3, prio) endif return 1 endfunctionNote
- It’ll be best to also define the other functions I have in all my autoload plugins in order to simplify logging and debugging.
- I highly recommand you take the time to write some unit tests – yeah, I know, I haven’t written them for all possible cases supported by lh-style.
Todo
- Describe
!cursorhere!
,!mark!
andlh#marker#txt()
- Describe negative pattern
- Describe how priorities applies
- Describe other ways to dispatch
- Describe
none()
Low-level style configuration¶
Historically, there wasn’t any way to group style configurations as :UseStyle
.
permits. We add to define everything manually, and switching from one complex
configuration to another was tedious.
While using :UseStyle
. is now the preferred method, we can still use the low level method.
:AddStyle key [-buffer] [-ft[=ft]] [-prio=prio] Replacement
¶
key
is a regex that will get replaced automatically (by plugins supporting this API)replacement
is what will be inserted in place ofkey
-buffer
defines this association only for the current buffer. This option is meant to be used with plugins like local_vimrc.-ft[=ft]
defines this association only for the specified filetype. Whenft
is not specified, it applies only to the current filetype. This option is meant to be used in .vimrc, in the global zone of filetype-plugins or possibly in local_vimrcs (when combined with-buffer
).-prio=prio
Sets a priority that’ll be used to determine which key is matching the text to enhance. By default all styles have a priority of 1. The typical application is to have template expander ignore single curly brackets.
Note
Local configuration (with -buffer
) have the priority over filetype specialized configuration (with -ft
).
(Deprecated) :AddStyle
Examples:¶
" # Space before open bracket in C & al {{{2
" A little space before all C constructs in C and child languages
" NB: the spaces isn't put before all open brackets
AddStyle if( -ft=c if\ (
AddStyle while( -ft=c while\ (
AddStyle for( -ft=c for\ (
AddStyle switch( -ft=c switch\ (
AddStyle catch( -ft=cpp catch\ (
" # Ignore style in comments after curly brackets {{{2
AddStyle {\ *// -ft=c &
AddStyle }\ *// -ft=c &
" # Multiple C++ namespaces on same line {{{2
AddStyle {\ *namespace -ft=cpp &
AddStyle }\ *} -ft=cpp &
" # Doxygen {{{2
" Doxygen Groups
AddStyle @{ -ft=c @{
AddStyle @} -ft=c @}
" Doxygen Formulas
AddStyle \\f{ -ft=c \\\\f{
AddStyle \\f} -ft=c \\\\f}
" # Default style in C & al: Stroustrup/K&R {{{2
AddStyle { -ft=c -prio=10 {\n
AddStyle }; -ft=c -prio=10 \n};\n
AddStyle } -ft=c -prio=10 \n}
" # Inhibated style in C & al: Allman, Whitesmiths, Pico {{{2
" AddStyle { -ft=c -prio=10 \n{\n
" AddStyle }; -ft=c -prio=10 \n};\n
" AddStyle } -ft=c -prio=10 \n}\n
" # Ignore curly-brackets on single lines {{{2
AddStyle ^\ *{\ *$ -ft=c &
AddStyle ^\ *}\ *$ -ft=c &
" # Handle specifically empty pairs of curly-brackets {{{2
" On its own line
" -> Leave it be
AddStyle ^\ *{}\ *$ -ft=c &
" -> Split it
" AddStyle ^\ *{}\ *$ -ft=c {\n}
" Mixed
" -> Split it
" AddStyle {} -ft=c -prio=5 {\n}
" -> On the next line (unsplit)
AddStyle {} -ft=c -prio=5 \n{}
" -> On the next line (split)
" AddStyle {} -ft=c -prio=5 \n{\n}
" # Java style {{{2
" Force Java style in Java
AddStyle { -ft=java -prio=10 {\n
AddStyle } -ft=java -prio=10 \n}
When you wish to adopt Allman coding style, in $project_root/_vimrc_local.vim
AddStyle { -b -ft=c -prio=10 \n{\n
AddStyle } -b -ft=c -prio=10 \n}