Merge #7735 'runtime fixes, doc updates'

This commit is contained in:
Justin M. Keyes
2017-12-27 12:53:54 +01:00
committed by GitHub
10 changed files with 483 additions and 208 deletions

View File

@@ -174,7 +174,7 @@ function! s:check_terminal() abort
\ .(empty(kbs_entry) ? '? (not found)' : kdch1_entry))
endif
for env_var in ['XTERM_VERSION', 'VTE_VERSION', 'TERM_PROGRAM', 'COLORTERM', 'SSH_TTY']
if !exists('$'.env_var)
if exists('$'.env_var)
call health#report_info(printf("$%s='%s'", env_var, eval('$'.env_var)))
endif
endfor

View File

@@ -512,27 +512,27 @@ nvim_parse_expression({expr}, {flags}, {highlight})
[start_col, end_col)).
Return:~
AST: top-level dictionary holds keys "error": Dictionary
with error, present only if parser saw some error.
Contains the following keys: "message": String, error
message in printf format, translated. Must contain exactly
one "%.*s". "arg": String, error message argument. "len":
Amount of bytes successfully parsed. With flags equal to
"" that should be equal to the length of expr string.
@note: “Sucessfully parsed” here means “participated in
AST creation”, not “till the first error”. "ast": AST,
either nil or a dictionary with these keys: "type": node
type, one of the value names from ExprASTNodeType
stringified without "kExprNode" prefix. "start": a pair
[line, column] describing where node is “started” where
"line" is always 0 (will not be 0 if you will be using
nvim_parse_viml() on e.g. ":let", but that is not present
yet). Both elements are Integers. "len": “length” of the
node. This and "start" are there for debugging purposes
primary (debugging parser and providing debug
information). "children": a list of nodes described in
top/"ast". There always is zero, one or two children, key
will not be present if node has no children. Maximum
AST: top-level dictionary with these keys: "error":
Dictionary with error, present only if parser saw some
error. Contains the following keys: "message": String,
error message in printf format, translated. Must contain
exactly one "%.*s". "arg": String, error message argument.
"len": Amount of bytes successfully parsed. With flags
equal to "" that should be equal to the length of expr
string. @note: “Sucessfully parsed” here means
“participated in AST creation”, not “till the first
error”. "ast": AST, either nil or a dictionary with these
keys: "type": node type, one of the value names from
ExprASTNodeType stringified without "kExprNode" prefix.
"start": a pair [line, column] describing where node is
“started” where "line" is always 0 (will not be 0 if you
will be using nvim_parse_viml() on e.g. ":let", but that
is not present yet). Both elements are Integers. "len":
“length” of the node. This and "start" are there for
debugging purposes primary (debugging parser and providing
debug information). "children": a list of nodes described
in top/"ast". There always is zero, one or two children,
key will not be present if node has no children. Maximum
number of children may be found in node_maxchildren array.
Local values (present only for certain nodes): "scope": a
single Integer, specifies scope for "Option" and
@@ -1047,4 +1047,4 @@ nvim_ui_try_resize({width}, {height}) *nvim_ui_try_resize()*
nvim_ui_set_option({name}, {value}) *nvim_ui_set_option()*
TODO: Documentation
vim:tw=78:ts=8:ft=help:norl:
vim:tw=78:ts=8:ft=help:norl:

View File

@@ -4,9 +4,9 @@
NVIM REFERENCE MANUAL by Thiago de Arruda
Nvim's facilities for async io *channel*
Nvim asynchronous IO *channel*
Type <M-]> to see the table of contents.
Type |gO| to see the table of contents.
==============================================================================
1. Introduction *channel-intro*

View File

@@ -270,9 +270,9 @@ External UIs are expected to implement these common features:
- Send the "super" key (Windows key, Apple key) as a |<D-| chord.
Implementation ~
- Options can be monitored for changes by the |OptionSet| autocmd. E.g. if the
user sets the 'guifont' option, this autocmd notifies channel 42: >
autocmd OptionSet guifont call rpcnotify(42, 'option-changed', 'guifont', &guifont)
- UI-related options ('guifont', 'ambiwidth', …) are published in the
"option_set" |ui-global| event. The event is triggered when the UI first
connects to Nvim and whenever an option is changed by the user or a plugin.
vim:tw=78:ts=8:ft=help:norl:

View File

@@ -70,6 +70,7 @@ Providers
Ruby plugins |provider-ruby|
Shared data |shada|
Embedded terminal |terminal|
VimL parser |nvim_parse_expression()|
XDG base directories |xdg|
USER EXPERIENCE ~

View File

@@ -478,7 +478,7 @@ def gen_docs(config):
docs += '\n\n\n'
docs = docs.rstrip() + '\n\n'
docs += ' vim:tw=78:ts=8:ft=help:norl:'
docs += ' vim:tw=78:ts=8:ft=help:norl:\n'
doc_file = os.path.join(base_dir, 'runtime/doc', doc_filename)
delete_lines_below(doc_file, section_start_token)

View File

@@ -14,27 +14,26 @@ readonly BRANCH_PREFIX="vim-"
CREATED_FILES=()
usage() {
echo "Helper script for porting Vim patches. For more information, see"
echo "Port Vim patches to Neovim"
echo "https://github.com/neovim/neovim/wiki/Merging-patches-from-upstream-vim"
echo
echo "Usage: ${BASENAME} [-h | -l | -p vim-revision | -r pr-number]"
echo
echo "Options:"
echo " -h Show this message and exit."
echo " -l Show list of missing Vim patches."
echo " -L Print missing Vim patches in machine-readable form."
echo " -p {vim-revision} Download and generate the specified Vim patch."
echo " vim-revision can be a version number '8.0.xxx'"
echo " or a valid Git ref (hash, tag, etc.)."
echo " -P {vim-revision} Download, generate and apply the Vim patch."
echo " -g {vim-revision} Download the Vim patch vim-revision."
echo " vim-revision can be a version number of the "
echo " format '7.4.xxx' or a Git commit hash."
echo " -s Submit a vim-patch pull request to Neovim."
echo " -r {pr-number} Review a vim-patch pull request to Neovim."
echo " -l List missing Vim patches."
echo " -L List missing Vim patches (for scripts)."
echo " -M List all merged patch-numbers (at current v:version)."
echo " -p {vim-revision} Download and generate a Vim patch. vim-revision"
echo " can be a Vim version (8.0.xxx) or a Git hash."
echo " -P {vim-revision} Download, generate and apply a Vim patch."
echo " -g {vim-revision} Download a Vim patch."
echo " -s Create a vim-patch pull request."
echo " -r {pr-number} Review a vim-patch pull request."
echo ' -V Clone the Vim source code to $VIM_SOURCE_DIR.'
echo
echo "Set VIM_SOURCE_DIR to change where Vim's sources are stored."
echo "Default is '${VIM_SOURCE_DIR_DEFAULT}'."
echo ' $VIM_SOURCE_DIR controls where Vim sources are found'
echo " (default: '${VIM_SOURCE_DIR_DEFAULT}')"
}
# Checks if a program is in the user's PATH, and is executable.
@@ -173,7 +172,7 @@ preprocess_patch() {
# Rename src/ paths to src/nvim/
LC_ALL=C sed -e 's/\( [ab]\/src\)/\1\/nvim/g' \
"$file" > "$file".tmp && mv "$file".tmp "$file"
# Rename path to matchit plugin.
LC_ALL=C sed -e 's@\( [ab]/runtime\)/pack/dist/opt/matchit/\(plugin/matchit.vim\)@\1/\2@g' \
"$file" > "$file".tmp && mv "$file".tmp "$file"
@@ -199,7 +198,7 @@ get_vim_patch() {
echo "$patch_content" > "${NVIM_SOURCE_DIR}/${patch_file}"
printf "Pre-processing patch...\n"
preprocess_patch "${NVIM_SOURCE_DIR}/${patch_file}"
preprocess_patch "${NVIM_SOURCE_DIR}/${patch_file}"
printf "✔ Saved patch to '${NVIM_SOURCE_DIR}/${patch_file}'.\n"
}
@@ -328,31 +327,52 @@ submit_pr() {
patch_file="vim-${patch_file}.patch"
if [[ ! -f "${NVIM_SOURCE_DIR}/${patch_file}" ]]; then
continue
fi
rm -- "${NVIM_SOURCE_DIR}/${patch_file}"
echo "✔ Removed '${NVIM_SOURCE_DIR}/${patch_file}'."
done
}
# Gets all Vim commits since the "start" commit.
list_vim_commits() { (
cd "${VIM_SOURCE_DIR}" && git log --reverse --format='%H' v8.0.0000..HEAD
) }
# Prints all (sorted) "vim-patch:xxx" tokens found in the Nvim git log.
list_vimpatch_tokens() {
local tokens
# Find all "vim-patch:xxx" tokens in the Nvim git log.
tokens="$(cd "${NVIM_SOURCE_DIR}" && git log -E --grep='vim-patch:[^ ]+' | grep 'vim-patch')"
echo "$tokens" | grep -E 'vim-patch:[^ ,{]{7,}' \
| sed 's/.*\(vim-patch:[.0-9a-z]\+\).*/\1/' \
| sort \
| uniq
}
# Prints all patch-numbers (for the current v:version) for which there is
# a "vim-patch:xxx" token in the Nvim git log.
list_vimpatch_numbers() {
# Transform "vim-patch:X.Y.ZZZZ" to "ZZZZ".
rm -- "${NVIM_SOURCE_DIR}/${patch_file}"
echo "✔ Removed '${NVIM_SOURCE_DIR}/${patch_file}'."
done
}
list_vimpatch_tokens | while read vimpatch_token; do
echo "$vimpatch_token" | grep '8\.0\.' | sed 's/.*vim-patch:8\.0\.\([0-9a-z]\+\).*/\1/'
done
}
list_vim_patches() {
# Get missing Vim commits
local vim_commits
# Prints a newline-delimited list of Vim commits, for use by scripts.
list_missing_vimpatches() {
local tokens vim_commit vim_commits is_missing vim_tag patch_number
local tokens
tokens="$(cd "${NVIM_SOURCE_DIR}" && git log -E --grep='vim-patch:[^ ]+' | grep 'vim-patch')"
tokens="$(for i in $tokens ; do echo "$i" | grep -E 'vim-patch:[^ ]{7}' | sed 's/.*\(vim-patch:[.0-9a-z]\+\).*/\1/' ; done)"
local vim_commit
# Find all "vim-patch:xxx" tokens in the Nvim git log.
tokens="$(list_vimpatch_tokens)"
# Get missing Vim commits
vim_commits="$(list_vim_commits)"
for vim_commit in ${vim_commits}; do
# Check for vim-patch:<commit_hash> (usually runtime updates).
local is_missing
is_missing="$(echo "$tokens" | >/dev/null 2>&1 grep "vim\-patch:${vim_commit:0:7}" && echo false || echo true)"
if ! [ "$is_missing" = "false" ] \
&& vim_tag="$(cd "${VIM_SOURCE_DIR}" && git describe --tags --exact-match "${vim_commit}" 2>/dev/null)"
vim_tag="$(cd "${VIM_SOURCE_DIR}" && git describe --tags --exact-match "${vim_commit}" 2>/dev/null)" || true
if [[ -n "${vim_tag}" ]]; then
# Vim version number (not commit hash).
then
# Vim version number (not commit hash).
# Check for vim-patch:<tag> (not commit hash).
@@ -362,11 +382,11 @@ list_vim_patches() {
fi
if ! [ "$is_missing" = "false" ]; then
echo "${vim_commit}"
echo "${vim_commit}"
fi
done
}
# Prints a human-formatted list of Vim commits, with instructional messages.
show_vimpatches() {
get_vim_sources
@@ -440,7 +460,7 @@ review_commit() {
echo "${commit_message#${git_patch_prefix}}"
fi
echo
echo
echo "Creating files."
echo "${nvim_patch}" > "${NVIM_SOURCE_DIR}/n${patch_file}"
echo "✔ Saved pull request diff to '${NVIM_SOURCE_DIR}/n${patch_file}'."
@@ -481,18 +501,22 @@ review_pr() {
if [[ "${reply}" == n ]]; then
break
fi
fi
fi
done
clean_files
}
while getopts "hlLMVp:P:g:r:s" opt; do
case ${opt} in
case ${opt} in
h)
usage
exit 0
;;
;;
l)
show_vimpatches
exit 0
;;
L)
list_missing_vimpatches
exit 0
@@ -504,7 +528,7 @@ while getopts "hlLp:P:g:r:s" opt; do
p)
stage_patch "${OPTARG}"
exit 0
;;
;;
P)
stage_patch "${OPTARG}" TRY_APPLY
exit 0
@@ -515,6 +539,10 @@ while getopts "hlLp:P:g:r:s" opt; do
;;
r)
review_pr "${OPTARG}"
exit 0
;;
s)
submit_pr
exit 0
;;
V)

67
scripts/vimpatch.lua Executable file
View File

@@ -0,0 +1,67 @@
-- Updates version.c list of applied Vim patches.
--
-- Usage:
-- VIM_SOURCE_DIR=~/neovim/.vim-src/ nvim -i NONE -u NONE --headless +'luafile ./scripts/vimpatch.lua' +q
local nvim = vim.api
local function pprint(o)
print(nvim.nvim_call_function('string', { o }))
end
local function systemlist(...)
local rv = nvim.nvim_call_function('systemlist', ...)
local err = nvim.nvim_get_vvar('shell_error')
local args_str = nvim.nvim_call_function('string', ...)
if 0 ~= err then
error('command failed: '..args_str)
end
return rv
end
local function vimpatch_sh_list_numbers()
return systemlist( { { 'bash', '-c', 'scripts/vim-patch.sh -M', } } )
end
-- Generates the lines to be inserted into the src/version.c
-- `included_patches[]` definition.
local function gen_version_c_lines()
-- Set of merged Vim 8.0.zzzz patch numbers.
local merged_patch_numbers = {}
local highest = 0
for _, n in ipairs(vimpatch_sh_list_numbers()) do
if n then
merged_patch_numbers[tonumber(n)] = true
highest = math.max(highest, n)
end
end
local lines = {}
for i = highest, 0, -1 do
local is_merged = (nil ~= merged_patch_numbers[i])
if is_merged then
table.insert(lines, string.format(' %s,', i))
else
table.insert(lines, string.format(' // %s,', i))
end
end
return lines
end
local function patch_version_c()
local lines = gen_version_c_lines()
nvim.nvim_command('silent noswapfile noautocmd edit src/nvim/version.c')
nvim.nvim_command('/static const int included_patches')
-- Delete the existing lines.
nvim.nvim_command('silent normal! j0d/};\rk')
-- Insert the lines.
nvim.nvim_call_function('append', {
nvim.nvim_eval('line(".")'),
lines,
})
nvim.nvim_command('silent write')
end
patch_version_c()

View File

@@ -929,7 +929,7 @@ typedef kvec_withinit_t(ExprASTConvStackItem, 16) ExprASTConvStack;
/// starting column and ending column (latter exclusive:
/// one should highlight region [start_col, end_col)).
///
/// @return AST: top-level dictionary holds keys
/// @return AST: top-level dictionary with these keys:
///
/// "error": Dictionary with error, present only if parser saw some
/// error. Contains the following keys:

View File

@@ -146,7 +146,7 @@ static const int included_patches[] = {
// 1292,
// 1291,
// 1290,
// 1289,
1289,
// 1288,
// 1287,
// 1286,
@@ -228,8 +228,187 @@ static const int included_patches[] = {
// 1210,
// 1209,
// 1208,
// 1207,
1207,
1206,
// 1205,
// 1204,
// 1203,
// 1202,
// 1201,
// 1200,
// 1199,
// 1198,
// 1197,
// 1196,
// 1195,
// 1194,
// 1193,
// 1192,
// 1191,
// 1190,
1189,
// 1188,
// 1187,
// 1186,
// 1185,
// 1184,
// 1183,
// 1182,
// 1181,
// 1180,
// 1179,
// 1178,
// 1177,
// 1176,
// 1175,
// 1174,
// 1173,
// 1172,
// 1171,
// 1170,
// 1169,
// 1168,
// 1167,
// 1166,
// 1165,
// 1164,
// 1163,
// 1162,
// 1161,
// 1160,
// 1159,
// 1158,
// 1157,
// 1156,
// 1155,
// 1154,
// 1153,
// 1152,
// 1151,
// 1150,
// 1149,
// 1148,
// 1147,
// 1146,
// 1145,
// 1144,
// 1143,
// 1142,
// 1141,
// 1140,
// 1139,
// 1138,
// 1137,
// 1136,
// 1135,
// 1134,
// 1133,
// 1132,
// 1131,
// 1130,
// 1129,
// 1128,
// 1127,
// 1126,
// 1125,
// 1124,
// 1123,
// 1122,
// 1121,
// 1120,
// 1119,
// 1118,
// 1117,
// 1116,
// 1115,
// 1114,
// 1113,
// 1112,
// 1111,
// 1110,
// 1109,
1108,
// 1107,
// 1106,
// 1105,
// 1104,
// 1103,
// 1102,
// 1101,
// 1100,
// 1099,
// 1098,
// 1097,
// 1096,
// 1095,
// 1094,
// 1093,
// 1092,
// 1091,
// 1090,
// 1089,
// 1088,
// 1087,
// 1086,
// 1085,
// 1084,
// 1083,
// 1082,
// 1081,
// 1080,
// 1079,
// 1078,
// 1077,
// 1076,
// 1075,
// 1074,
// 1073,
// 1072,
// 1071,
// 1070,
// 1069,
// 1068,
// 1067,
// 1066,
// 1065,
// 1064,
// 1063,
// 1062,
// 1061,
// 1060,
// 1059,
// 1058,
// 1057,
// 1056,
// 1055,
// 1054,
// 1053,
// 1052,
// 1051,
// 1050,
// 1049,
// 1048,
// 1047,
// 1046,
// 1045,
// 1044,
// 1043,
// 1042,
// 1041,
// 1040,
// 1039,
// 1038,
// 1037,
// 1036,
// 1035,
// 1034,
// 1033,
// 1032,
// 1031,
// 1030,
// 1029,
// 1028,
// 1027,
// 1026,
1025,
1024,
@@ -237,7 +416,7 @@ static const int included_patches[] = {
// 1022,
// 1021,
// 1020,
// 1019,
1019,
// 1018,
// 1017,
// 1016,
@@ -294,7 +473,7 @@ static const int included_patches[] = {
// 965,
// 964,
// 963,
// 962,
962,
// 961,
// 960,
// 959,
@@ -650,7 +829,7 @@ static const int included_patches[] = {
// 609,
// 608,
607,
// 606,
606,
605,
// 604,
// 603,
@@ -659,30 +838,30 @@ static const int included_patches[] = {
// 600,
// 599,
// 598,
// 597,
597,
// 596,
// 595,
595,
// 594,
// 593,
// 592,
// 591,
// 590,
590,
// 589,
// 588,
// 587,
// 586,
// 585,
// 584,
584,
// 583,
// 582,
// 581,
// 580,
// 579,
580,
579,
// 578,
// 577,
// 576,
// 575,
// 574,
574,
// 573,
// 572,
571,
@@ -691,7 +870,7 @@ static const int included_patches[] = {
// 568,
// 567,
// 566,
// 565,
565,
// 564,
// 563,
// 562,
@@ -720,7 +899,7 @@ static const int included_patches[] = {
// 539,
// 538,
// 537,
// 536,
536,
// 535,
// 534,
// 533,
@@ -739,7 +918,7 @@ static const int included_patches[] = {
// 520,
// 519,
518,
// 517,
517,
// 516,
// 515,
// 514,
@@ -772,7 +951,7 @@ static const int included_patches[] = {
487,
486,
485,
// 484,
484,
483,
482,
// 481,
@@ -836,7 +1015,7 @@ static const int included_patches[] = {
// 423,
// 422,
// 421,
// 420,
420,
// 419,
// 418,
// 417,
@@ -851,12 +1030,12 @@ static const int included_patches[] = {
408,
407,
// 406,
// 405 NA
// 404,
405,
404,
// 403,
// 402,
// 401,
// 400 NA
400,
// 399,
// 398,
// 397,
@@ -877,7 +1056,7 @@ static const int included_patches[] = {
// 382,
// 381,
// 380,
// 379,
379,
378,
377,
376,
@@ -936,7 +1115,7 @@ static const int included_patches[] = {
// 323,
322,
// 321,
// 320,
320,
319,
// 318,
// 317,
@@ -946,18 +1125,18 @@ static const int included_patches[] = {
// 313,
// 312,
311,
// 310,
// 309,
310,
309,
308,
307,
306,
305,
// 304,
// 303,
// 302 NA
302,
// 301,
300,
// 299,
299,
298,
297,
// 296,
@@ -968,38 +1147,38 @@ static const int included_patches[] = {
291,
290,
289,
// 288 NA
288,
287,
// 286,
// 285 NA
// 284 NA
285,
284,
283,
282,
// 281 NA
281,
280,
// 279 NA
// 278 NA
// 277 NA
// 276 NA
279,
278,
277,
276,
275,
274,
// 273 NA
// 272 NA
// 271 NA
// 270 NA
// 269 NA
// 268 NA
// 267 NA
273,
272,
271,
270,
269,
268,
267,
266,
// 265,
// 264,
// 263,
// 262,
// 261,
// 260 NA
260,
259,
258,
// 257 NA
257,
// 256,
// 255,
// 254,
@@ -1007,45 +1186,45 @@ static const int included_patches[] = {
// 252,
// 251,
250,
// 249 NA
// 248 NA
249,
248,
247,
// 246 NA
246,
245,
// 244 NA
244,
243,
242,
// 241 NA
// 240 NA
// 239 NA
241,
240,
239,
// 238,
237,
// 236,
235,
// 234,
// 233,
// 232 NA
232,
// 231,
// 230,
229,
// 228,
// 227,
227,
226,
// 225,
224,
223,
// 222,
// 221 NA
221,
// 220,
219,
218,
// 217 NA
217,
// 216,
// 215 NA
215,
// 214,
// 213 NA
213,
// 212,
// 211 NA
211,
// 210,
209,
208,
@@ -1053,49 +1232,49 @@ static const int included_patches[] = {
206,
205,
// 204,
// 203 NA
203,
// 202,
// 201,
// 200,
// 199 NA
199,
// 198,
// 197,
196,
195,
194,
// 193 NA
// 192 NA
// 191 NA
193,
192,
191,
190,
189,
188,
// 187 NA
187,
186,
// 185,
// 184,
// 183 NA
183,
182,
181,
// 180 NA
180,
179,
178,
177,
176,
// 175,
174,
// 173 NA
173,
172,
// 171 NA
// 170 NA
// 169 NA
171,
170,
169,
168,
167,
// 166 NA
166,
165,
164,
// 163 NA
// 162 NA
// 161 NA
163,
162,
161,
// 160,
159,
158,
@@ -1104,21 +1283,21 @@ static const int included_patches[] = {
155,
// 154,
// 153,
// 152 NA
152,
// 151,
150,
149,
148,
147,
146,
// 145 NA
// 144 NA
145,
144,
143,
142,
// 141 NA
141,
140,
// 139 NA
// 138 NA
139,
138,
137,
136,
135,
@@ -1126,137 +1305,137 @@ static const int included_patches[] = {
133,
132,
131,
// 130 NA
// 129 NA
130,
129,
128,
127,
126,
125,
124,
// 123 NA
// 122 NA
123,
122,
121,
// 120 NA
120,
119,
118,
// 117 NA
117,
116,
// 115 NA
// 114 NA
// 113 NA
115,
114,
113,
112,
111,
110,
// 109 NA
// 108 NA
// 107 NA
109,
108,
107,
106,
// 105 NA
105,
104,
// 103 NA
103,
102,
101,
100,
99,
// 98 NA
// 97 NA
98,
97,
96,
// 95 NA
// 94 NA
// 93 NA
95,
94,
93,
92,
91,
90,
// 89 NA
89,
88,
// 87 NA
87,
86,
85,
84,
83,
// 82 NA
82,
81,
// 80 NA
80,
79,
78,
// 77 NA
// 76 NA
77,
76,
75,
74,
73,
// 72 NA
// 71 NA
// 70 NA
72,
71,
70,
69,
68,
// 67 NA
67,
66,
// 65 NA
65,
64,
// 63 NA
63,
62,
// 61 NA
61,
60,
// 59 NA
59,
58,
57,
56,
// 55 NA
// 54 NA
55,
54,
53,
52,
// 51 NA
// 50 NA
51,
50,
49,
// 48 NA
48,
47,
46,
// 45 NA
45,
44,
43,
42,
41,
40,
// 39 NA
39,
38,
37,
// 36 NA
36,
35,
34,
33,
32,
31,
// 30 NA
// 29 NA
// 28 NA
// 27 NA
30,
29,
28,
27,
26,
25,
// 24 NA
24,
23,
// 22 NA
// 21 NA
22,
21,
20,
19,
// 18 NA
18,
17,
// 16 NA
// 15 NA
// 14 NA
// 13 NA
16,
15,
14,
13,
12,
// 11 NA
// 10 NA
// 9 NA
11,
10,
9,
8,
// 7 NA
7,
6,
// 5 NA
5,
4,
3,
2,
1,
0
0,
};
// clang-format on