diff options
Diffstat (limited to 'scripts')
-rw-r--r-- | scripts/gen_events.lua | 65 | ||||
-rw-r--r-- | scripts/genoptions.lua | 183 | ||||
-rw-r--r-- | scripts/genvimvim.lua | 138 | ||||
-rw-r--r-- | scripts/msgpack-gen.lua | 6 | ||||
-rwxr-xr-x | scripts/vim-patch.sh | 172 |
5 files changed, 518 insertions, 46 deletions
diff --git a/scripts/gen_events.lua b/scripts/gen_events.lua new file mode 100644 index 0000000000..75e0b3da3a --- /dev/null +++ b/scripts/gen_events.lua @@ -0,0 +1,65 @@ +if arg[1] == '--help' then + print('Usage: gen_events.lua src/nvim enum_file event_names_file') + os.exit(0) +end + +local nvimsrcdir = arg[1] +local fileio_enum_file = arg[2] +local names_file = arg[3] + +package.path = nvimsrcdir .. '/?.lua;' .. package.path + +local auevents = require('auevents') +local events = auevents.events +local aliases = auevents.aliases + +enum_tgt = io.open(fileio_enum_file, 'w') +names_tgt = io.open(names_file, 'w') + +enum_tgt:write('typedef enum auto_event {') +names_tgt:write([[ +static const struct event_name { + size_t len; + char *name; + event_T event; +} event_names[] = {]]) + +for i, event in ipairs(events) do + if i > 1 then + comma = ',\n' + else + comma = '\n' + end + enum_tgt:write(('%s EVENT_%s = %u'):format(comma, event:upper(), i - 1)) + names_tgt:write(('%s {%u, "%s", EVENT_%s}'):format(comma, #event, event, event:upper())) +end + +for alias, event in pairs(aliases) do + names_tgt:write((',\n {%u, "%s", EVENT_%s}'):format(#alias, alias, event:upper())) +end + +names_tgt:write(',\n {0, NULL, (event_T)0}') + +enum_tgt:write('\n} event_T;\n') +names_tgt:write('\n};\n') + +enum_tgt:write(('\n#define NUM_EVENTS %u\n'):format(#events)) +names_tgt:write('\nstatic AutoPat *first_autopat[NUM_EVENTS] = {\n ') +line_len = 1 +for i = 1,((#events) - 1) do + line_len = line_len + #(' NULL,') + if line_len > 80 then + names_tgt:write('\n ') + line_len = 1 + #(' NULL,') + end + names_tgt:write(' NULL,') +end +if line_len + #(' NULL') > 80 then + names_tgt:write('\n NULL') +else + names_tgt:write(' NULL') +end +names_tgt:write('\n};\n') + +enum_tgt:close() +names_tgt:close() diff --git a/scripts/genoptions.lua b/scripts/genoptions.lua new file mode 100644 index 0000000000..2859ca1795 --- /dev/null +++ b/scripts/genoptions.lua @@ -0,0 +1,183 @@ +if arg[1] == '--help' then + print('Usage: genoptions.lua src/nvim options_file') + os.exit(0) +end + +local nvimsrcdir = arg[1] +local options_file = arg[2] + +package.path = nvimsrcdir .. '/?.lua;' .. package.path + +local opt_fd = io.open(options_file, 'w') + +local w = function(s) + if s:match('^ %.') then + opt_fd:write(s .. ',\n') + else + opt_fd:write(s .. '\n') + end +end + +local options = require('options') + +cstr = options.cstr + +local type_flags={ + bool='P_BOOL', + number='P_NUM', + string='P_STRING', +} + +local redraw_flags={ + statuslines='P_RSTAT', + current_window='P_RWIN', + current_buffer='P_RBUF', + all_windows='P_RALL', + everything='P_RCLR', + curswant='P_CURSWANT', +} + +local list_flags={ + comma='P_COMMA', + flags='P_FLAGLIST', + flagscomma='P_COMMA|P_FLAGLIST', +} + +local get_flags = function(o) + local ret = {type_flags[o.type]} + local add_flag = function(f) + ret[1] = ret[1] .. '|' .. f + end + if o.list then + add_flag(list_flags[o.list]) + end + if o.redraw then + for _, r_flag in ipairs(o.redraw) do + add_flag(redraw_flags[r_flag]) + end + end + for _, flag_desc in ipairs({ + {'alloced'}, + {'expand'}, + {'nodefault'}, + {'no_mkrc'}, + {'vi_def'}, + {'vim'}, + {'secure'}, + {'gettext'}, + {'noglob'}, + {'normal_fname_chars', 'P_NFNAME'}, + {'pri_mkrc'}, + {'deny_in_modelines', 'P_NO_ML'}, + {'deny_duplicates', 'P_NODUP'}, + }) do + local key_name = flag_desc[1] + local def_name = flag_desc[2] or ('P_' .. key_name:upper()) + if o[key_name] then + add_flag(def_name) + end + end + return ret[1] +end + +local get_cond +get_cond = function(c, base_string) + local cond_string = base_string or '#if ' + if type(c) == 'table' then + cond_string = cond_string .. get_cond(c[1], '') + for i, subc in ipairs(c) do + if i > 1 then + cond_string = cond_string .. ' && ' .. get_cond(subc, '') + end + end + elseif c:sub(1, 1) == '!' then + cond_string = cond_string .. '!defined(' .. c:sub(2) .. ')' + else + cond_string = cond_string .. 'defined(' .. c .. ')' + end + return cond_string +end + +value_dumpers = { + ['function']=function(v) return v() end, + string=cstr, + boolean=function(v) return v and 'true' or 'false' end, + number=function(v) return ('%iL'):format(v) end, + ['nil']=function(v) return '0L' end, +} + +local get_value = function(v) + return '(char_u *) ' .. value_dumpers[type(v)](v) +end + +local get_defaults = function(d) + return '{' .. get_value(d.vi) .. ', ' .. get_value(d.vim) .. '}' +end + +local defines = {} + +local dump_option = function(i, o) + w(' [' .. ('%u'):format(i - 1) .. ']={') + w(' .fullname=' .. cstr(o.full_name)) + if o.abbreviation then + w(' .shortname=' .. cstr(o.abbreviation)) + end + w(' .flags=' .. get_flags(o)) + if o.enable_if then + w(get_cond(o.enable_if)) + end + if o.varname then + w(' .var=(char_u *)&' .. o.varname) + elseif #o.scope == 1 and o.scope[1] == 'window' then + w(' .var=VAR_WIN') + end + if o.enable_if then + w('#endif') + end + if #o.scope == 1 and o.scope[1] == 'global' then + w(' .indir=PV_NONE') + else + assert (#o.scope == 1 or #o.scope == 2) + assert (#o.scope == 1 or o.scope[1] == 'global') + local min_scope = o.scope[#o.scope] + local varname = o.pv_name or o.varname or ( + 'p_' .. (o.abbreviation or o.full_name)) + local pv_name = ( + 'OPT_' .. min_scope:sub(1, 3):upper() .. '(' .. ( + min_scope:sub(1, 1):upper() .. 'V_' .. varname:sub(3):upper() + ) .. ')' + ) + if #o.scope == 2 then + pv_name = 'OPT_BOTH(' .. pv_name .. ')' + end + defines['PV_' .. varname:sub(3):upper()] = pv_name + w(' .indir=' .. pv_name) + end + if o.defaults then + if o.defaults.condition then + w(get_cond(o.defaults.condition)) + end + w(' .def_val=' .. get_defaults(o.defaults.if_true)) + if o.defaults.condition then + if o.defaults.if_false then + w('#else') + w(' .def_val=' .. get_defaults(o.defaults.if_false)) + end + w('#endif') + end + end + w(' },') +end + +w('static vimoption_T options[] = {') +for i, o in ipairs(options.options) do + dump_option(i, o) +end +w(' [' .. ('%u'):format(#options.options) .. ']={.fullname=NULL}') +w('};') +w('') + +for k, v in pairs(defines) do + w('#define ' .. k .. ' ' .. v) +end +opt_fd:close() diff --git a/scripts/genvimvim.lua b/scripts/genvimvim.lua new file mode 100644 index 0000000000..9135c8e3ab --- /dev/null +++ b/scripts/genvimvim.lua @@ -0,0 +1,138 @@ +if arg[1] == '--help' then + print('Usage: genoptions.lua src/nvim runtime/syntax/vim/generated.vim') + os.exit(0) +end + +local nvimsrcdir = arg[1] +local syntax_file = arg[2] + +package.path = nvimsrcdir .. '/?.lua;' .. package.path + +local lld = {} +local syn_fd = io.open(syntax_file, 'w') +lld.line_length = 0 +local w = function(s) + syn_fd:write(s) + if s:find('\n') then + lld.line_length = #(s:gsub('.*\n', '')) + else + lld.line_length = lld.line_length + #s + end +end + +local options = require('options') +local auevents = require('auevents') +local ex_cmds = require('ex_cmds') + +local cmd_kw = function(prev_cmd, cmd) + if not prev_cmd then + return cmd:sub(1, 1) .. '[' .. cmd:sub(2) .. ']' + else + local shift = 1 + while cmd:sub(shift, shift) == prev_cmd:sub(shift, shift) do + shift = shift + 1 + end + if shift >= #cmd then + return cmd + else + return cmd:sub(1, shift) .. '[' .. cmd:sub(shift + 1) .. ']' + end + end +end + +vimcmd_start = 'syn keyword vimCommand contained ' +w(vimcmd_start) +local prev_cmd = nil +for _, cmd_desc in ipairs(ex_cmds) do + if lld.line_length > 850 then + w('\n' .. vimcmd_start) + end + local cmd = cmd_desc.command + if cmd:match('%w') and cmd ~= 'z' then + w(' ' .. cmd_kw(prev_cmd, cmd)) + end + prev_cmd = cmd +end + +local vimopt_start = 'syn keyword vimOption contained ' +w('\n\n' .. vimopt_start) + +for _, opt_desc in ipairs(options.options) do + if not opt_desc.varname or opt_desc.varname:sub(1, 7) ~= 'p_force' then + if lld.line_length > 850 then + w('\n' .. vimopt_start) + end + w(' ' .. opt_desc.full_name) + if opt_desc.abbreviation then + w(' ' .. opt_desc.abbreviation) + end + if opt_desc.type == 'bool' then + w(' inv' .. opt_desc.full_name) + w(' no' .. opt_desc.full_name) + if opt_desc.abbreviation then + w(' inv' .. opt_desc.abbreviation) + w(' no' .. opt_desc.abbreviation) + end + end + end +end + +w('\n\nsyn case ignore') +local vimau_start = 'syn keyword vimAutoEvent contained ' +w('\n\n' .. vimau_start) + +for _, au in ipairs(auevents.events) do + if not auevents.neovim_specific[au] then + if lld.line_length > 850 then + w('\n' .. vimau_start) + end + w(' ' .. au) + end +end +for au, _ in pairs(auevents.aliases) do + if not auevents.neovim_specific[au] then + if lld.line_length > 850 then + w('\n' .. vimau_start) + end + w(' ' .. au) + end +end + +local nvimau_start = 'syn keyword nvimAutoEvent contained ' +w('\n\n' .. nvimau_start) + +for au, _ in pairs(auevents.neovim_specific) do + if lld.line_length > 850 then + w('\n' .. nvimau_start) + end + w(' ' .. au) +end + +w('\n\nsyn case match') +local vimfun_start = 'syn keyword vimFuncName contained ' +w('\n\n' .. vimfun_start) +eval_fd = io.open(nvimsrcdir .. '/eval.c', 'r') +local started = 0 +for line in eval_fd:lines() do + if line == '} functions[] =' then + started = 1 + elseif started == 1 then + assert (line == '{') + started = 2 + elseif started == 2 then + if line == '};' then + break + end + local func_name = line:match('^ {"(%w+)",') + if func_name then + if lld.line_length > 850 then + w('\n' .. vimfun_start) + end + w(' ' .. func_name) + end + end +end +eval_fd:close() + +w('\n') +syn_fd:close() diff --git a/scripts/msgpack-gen.lua b/scripts/msgpack-gen.lua index bb37ae94da..581641ae06 100644 --- a/scripts/msgpack-gen.lua +++ b/scripts/msgpack-gen.lua @@ -34,8 +34,8 @@ c_params = Ct(c_void + c_param_list) c_proto = Ct( Cg(c_type, 'return_type') * Cg(c_id, 'name') * fill * P('(') * fill * Cg(c_params, 'parameters') * fill * P(')') * - Cg(Cc(false), 'deferred') * - (fill * Cg((P('FUNC_ATTR_DEFERRED') * Cc(true)), 'deferred') ^ -1) * + Cg(Cc(false), 'async') * + (fill * Cg((P('FUNC_ATTR_ASYNC') * Cc(true)), 'async') ^ -1) * fill * P(';') ) grammar = Ct((c_proto + c_comment + c_preproc + ws) ^ 1) @@ -279,7 +279,7 @@ for i = 1, #functions do '(String) {.data = "'..fn.name..'", '.. '.size = sizeof("'..fn.name..'") - 1}, '.. '(MsgpackRpcRequestHandler) {.fn = handle_'.. fn.name.. - ', .defer = '..tostring(fn.deferred)..'});\n') + ', .async = '..tostring(fn.async)..'});\n') if #fn.name > max_fname_len then max_fname_len = #fn.name diff --git a/scripts/vim-patch.sh b/scripts/vim-patch.sh index f17b23101d..9ae9377d8f 100755 --- a/scripts/vim-patch.sh +++ b/scripts/vim-patch.sh @@ -1,6 +1,7 @@ #!/usr/bin/env bash set -e +set -u set -o pipefail readonly NEOVIM_SOURCE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" @@ -12,21 +13,31 @@ usage() { echo "Helper script for porting Vim patches. For more information, see" echo "https://github.com/neovim/neovim/wiki/Merging-patches-from-upstream-vim" echo - echo "Usage: ${BASENAME} [option]" - echo " ${BASENAME} vim-revision" + echo "Usage: ${BASENAME} [-h | -l | -p vim-revision | -r pr-number]" echo echo "Options:" - echo " -h, --help Show this message." - echo " -l, --list Show list of Vim patches missing from Neovim." - echo - echo "vim-revision can be a version number of the format '7.4.xxx'" - echo "or a Mercurial commit hash." + echo " -h Show this message and exit." + echo " -l Show list of Vim patches missing from Neovim." + echo " -p {vim-revision} Download and apply the Vim patch vim-revision." + echo " vim-revision can be a version number of the " + echo " format '7.4.xxx' or a Mercurial commit hash." + echo " -r {pr-number} Review a vim-patch pull request to Neovim." echo echo "Set VIM_SOURCE_DIR to change where Vim's sources are stored." echo "The default is '${VIM_SOURCE_DIR_DEFAULT}'." } +# Checks if a program is in the user's PATH, and is executable. +check_executable() { + if [[ ! -x $(command -v "${1}") ]]; then + >&2 echo "${BASENAME}: '${1}' not found in PATH or not executable." + exit 1 + fi +} + get_vim_sources() { + check_executable hg + echo "Retrieving Vim sources." if [[ ! -d ${VIM_SOURCE_DIR} ]]; then echo "Cloning Vim sources into '${VIM_SOURCE_DIR}'." @@ -41,20 +52,39 @@ get_vim_sources() { fi } -get_vim_patch() { +commit_message() { + echo "vim-patch:${vim_version} + +${vim_message} + +${vim_commit_url}" +} + +assign_commit_details() { if [[ ${1} =~ [0-9]\.[0-9]\.[0-9]{3,4} ]]; then # Interpret parameter as version number. vim_version="${1}" vim_commit="v${1//./-}" - strip_commit_line=true + local strip_commit_line=true vim_commit_url="https://github.com/vim/vim/commit/${vim_commit}" else # Interpret parameter as commit hash. vim_version="${1:0:7}" vim_commit="${1}" - strip_commit_line=false + local strip_commit_line=false vim_commit_url="https://code.google.com/p/vim/source/detail?r=${vim_commit}" fi + vim_message="$(hg log --template "{desc}" --rev "${vim_commit}")" + if [[ ${strip_commit_line} == "true" ]]; then + # Remove first line of commit message. + vim_message="$(echo "${vim_message}" | sed -e '1d')" + fi +} + +get_vim_patch() { + get_vim_sources + + assign_commit_details "${1}" hg log --rev "${vim_commit}" >/dev/null 2>&1 || { >&2 echo "✘ Couldn't find Vim revision '${vim_commit}'." @@ -65,19 +95,9 @@ get_vim_patch() { # Collect patch details and store into variables. vim_full="$(hg log --patch --git --verbose --rev "${vim_commit}")" - vim_message="$(hg log --template "{desc}" --rev "${vim_commit}")" - if [[ ${strip_commit_line} == "true" ]]; then - # Remove first line of commit message. - vim_message="$(echo "${vim_message}" | sed -e '1d')" - fi vim_diff="$(hg diff --show-function --git --change "${vim_commit}" \ | sed -e 's/\( [ab]\/src\)/\1\/nvim/g')" # Change directory to src/nvim. - neovim_message=" -vim-patch:${vim_version} - -${vim_message} - -${vim_commit_url}" + neovim_message="$(commit_message)" neovim_pr=" \`\`\` ${vim_message} @@ -108,7 +128,7 @@ ${vim_diff} echo echo "Creating files." echo "${vim_diff}" > "${NEOVIM_SOURCE_DIR}/${neovim_branch}.diff" - echo "✔ Saved patch to '${NEOVIM_SOURCE_DIR}/${neovim_branch}.diff'." + echo "✔ Saved diff to '${NEOVIM_SOURCE_DIR}/${neovim_branch}.diff'." echo "${vim_full}" > "${NEOVIM_SOURCE_DIR}/${neovim_branch}.patch" echo "✔ Saved full commit details to '${NEOVIM_SOURCE_DIR}/${neovim_branch}.patch'." echo "${neovim_pr}" > "${NEOVIM_SOURCE_DIR}/${neovim_branch}.pr" @@ -132,6 +152,8 @@ ${vim_diff} } list_vim_patches() { + get_vim_sources + echo echo "Vim patches missing from Neovim:" @@ -184,24 +206,88 @@ list_vim_patches() { echo " '${BASENAME} 1e8ebf870720e7b671f98f22d653009826304c4f'" } -if [[ ${1} == "--help" || ${1} == "-h" ]]; then - usage - exit 0 -elif [[ ${#} != 1 ]]; then - usage - exit 1 -fi - -# Checks if mercurial is in the user's PATH, and is executable. -if [[ ! -x $(command -v hg) ]]; then - >&2 echo "${BASENAME}: 'hg' (mercurial) not found in PATH or not executable" - exit 1 -fi - -get_vim_sources - -if [[ ${1} == "--list" || ${1} == "-l" ]]; then - list_vim_patches -else - get_vim_patch "${1}" -fi +review_pr() { + check_executable curl + check_executable nvim + + get_vim_sources + + local pr="${1}" + echo + echo "Downloading data for pull request #${pr}." + + local git_patch_prefix='Subject: \[PATCH\] ' + local neovim_patch="$(curl -Ssf "https://patch-diff.githubusercontent.com/raw/neovim/neovim/pull/${pr}.patch")" + echo "${neovim_patch}" > a + local vim_version="$(head -n 4 <<< "${neovim_patch}" | sed -n "s/${git_patch_prefix}vim-patch:\([a-z0-9.]*\)$/\1/p")" + + if [[ -n "${vim_version}" ]]; then + echo "✔ Detected Vim patch '${vim_version}'." + else + echo "✘ Could not detect the Vim patch number." + echo " This script assumes that the PR contains a single commit" + echo " with 'vim-patch:XXX' as its title." + exit 1 + fi + + assign_commit_details "${vim_version}" + + local expected_commit_message="$(commit_message)" + local message_length="$(wc -l <<< "${expected_commit_message}")" + local commit_message="$(tail -n +4 <<< "${neovim_patch}" | head -n "${message_length}")" + if [[ "${commit_message#${git_patch_prefix}}" == "${expected_commit_message}" ]]; then + echo "✔ Found expected commit message." + else + echo "✘ Wrong commit message." + echo " Expected:" + echo "${expected_commit_message}" + echo " Actual:" + echo "${commit_message#${git_patch_prefix}}" + exit 1 + fi + + local base_name="vim-${vim_version}" + echo + echo "Creating files." + curl -Ssfo "${NEOVIM_SOURCE_DIR}/n${base_name}.diff" "https://patch-diff.githubusercontent.com/raw/neovim/neovim/pull/${pr}.diff" + echo "✔ Saved pull request diff to '${NEOVIM_SOURCE_DIR}/n${base_name}.diff'." + echo "${neovim_patch}" > "${NEOVIM_SOURCE_DIR}/n${base_name}.patch" + echo "✔ Saved full pull request commit details to '${NEOVIM_SOURCE_DIR}/n${base_name}.patch'." + hg diff --show-function --git --change "${vim_commit}" > "${NEOVIM_SOURCE_DIR}/${base_name}.diff" + echo "✔ Saved Vim diff to '${NEOVIM_SOURCE_DIR}/${base_name}.diff'." + hg log --patch --git --verbose --rev "${vim_commit}" > "${NEOVIM_SOURCE_DIR}/${base_name}.patch" + echo "✔ Saved full Vim commit details to '${NEOVIM_SOURCE_DIR}/${base_name}.patch'." + echo "You can use 'git clean' to remove these files when you're done." + + echo + echo "Launching nvim." + exec nvim -O "${NEOVIM_SOURCE_DIR}/${base_name}.diff" "${NEOVIM_SOURCE_DIR}/n${base_name}.diff" +} + +while getopts "hlp:r:" opt; do + case ${opt} in + h) + usage + exit 0 + ;; + l) + list_vim_patches + exit 0 + ;; + p) + get_vim_patch "${OPTARG}" + exit 0 + ;; + r) + review_pr "${OPTARG}" + exit 0 + ;; + *) + exit 1 + ;; + esac +done + +usage + +# vim: et sw=2 |