Merge pull request #40228 from zeertzjq/vim-ff7fcb8

vim-patch: runtime file updates
This commit is contained in:
zeertzjq
2026-06-14 10:02:39 +08:00
committed by GitHub
9 changed files with 540 additions and 0 deletions

View File

@@ -11,6 +11,8 @@ paste.vim common code for mswin.vim and menu.vim
spellfile.vim downloading of a missing spell file
Omni completion files:
adacomplete.vim Ada
beancount.vim Beancount
ccomplete.vim C
csscomplete.vim HTML / CSS
htmlcomplete.vim HTML

View File

@@ -0,0 +1,59 @@
" Beancount specific formatting
" Language: beancount
" Maintainer: Nathan Grigg
" Latest Revision: 2021-03-06
" Align currency on decimal point.
function! beancount#align_commodity(line1, line2) abort
" Save cursor position to adjust it if necessary.
let l:cursor_col = col('.')
let l:cursor_line = line('.')
" Increment at start of loop, because of continue statements.
let l:current_line = a:line1 - 1
while l:current_line < a:line2
let l:current_line += 1
let l:line = getline(l:current_line)
" This matches an account name followed by a space in one of the two
" following cases:
" - A posting line, i.e., the line starts with indentation followed
" by an optional flag and the account.
" - A balance directive, i.e., the line starts with a date followed
" by the 'balance' keyword and the account.
" - A price directive, i.e., the line starts with a date followed by
" the 'price' keyword and a currency.
let l:end_account = matchend(l:line, '\v' .
\ '^[\-/[:digit:]]+\s+balance\s+([A-Z][A-Za-z0-9\-]+)(:[A-Z0-9][A-Za-z0-9\-]*)+ ' .
\ '|^[\-/[:digit:]]+\s+price\s+\S+ ' .
\ '|^\s+([!&#?%PSTCURM]\s+)?([A-Z][A-Za-z0-9\-]+)(:[A-Z0-9][A-Za-z0-9\-]*)+ '
\ )
if l:end_account < 0
continue
endif
" Where does the number begin?
let l:begin_number = matchend(l:line, '^ *', l:end_account)
" Look for a minus sign and a number (possibly containing commas) and
" align on the next column.
let l:separator = matchend(l:line, '^\v([-+])?[,[:digit:]]+', l:begin_number) + 1
if l:separator < 0 | continue | endif
let l:has_spaces = l:begin_number - l:end_account
let l:need_spaces = g:beancount_separator_col - l:separator + l:has_spaces
if l:need_spaces < 0 | continue | endif
call setline(l:current_line, l:line[0 : l:end_account - 1] . repeat(' ', l:need_spaces) . l:line[ l:begin_number : -1])
if l:current_line == l:cursor_line && l:cursor_col >= l:end_account
" Adjust cursor position for continuity.
call cursor(0, l:cursor_col + l:need_spaces - l:has_spaces)
endif
endwhile
endfunction
" Call bean-doctor on the current line and dump output into a scratch buffer
function! beancount#get_context() abort
let l:context = system('bean-doctor context ' . shellescape(expand('%')) . ' ' . line('.'))
botright new
setlocal buftype=nofile bufhidden=hide noswapfile
call append(0, split(l:context, '\v\n'))
normal! gg
endfunction

View File

@@ -0,0 +1,215 @@
" Vim completion script
" Language: beancount
" Maintainer: Nathan Grigg
" Latest Revision: 2021-03-06
let s:using_python3 = has('python3') || has('python3/dyn')
" Equivalent to python's startswith
" Matches based on user's ignorecase preference
function! s:startswith(string, prefix) abort
return strpart(a:string, 0, strlen(a:prefix)) == a:prefix
endfunction
function! s:count_expression(text, expression) abort
return len(split(a:text, a:expression, 1)) - 1
endfunction
function! s:sort_accounts_by_depth(name1, name2) abort
let l:depth1 = s:count_expression(a:name1, ':')
let l:depth2 = s:count_expression(a:name2, ':')
return l:depth1 == l:depth2 ? 0 : l:depth1 > l:depth2 ? 1 : -1
endfunction
let s:directives = ['open', 'close', 'commodity', 'txn', 'balance', 'pad', 'note', 'document', 'price', 'event', 'query', 'custom']
" ------------------------------
" Completion functions
" ------------------------------
function! beancountcomplete#complete(findstart, base) abort
if a:findstart
let l:col = searchpos('\s', 'bn', line('.'))[1]
if l:col == 0
return -1
else
return l:col
endif
endif
let l:partial_line = strpart(getline('.'), 0, getpos('.')[2]-1)
" Match directive types
if l:partial_line =~# '^\d\d\d\d\(-\|/\)\d\d\1\d\d $'
return beancountcomplete#complete_basic(s:directives, a:base, '')
endif
" If we are using python3, now is a good time to load everything
call beancountcomplete#load_everything()
" Split out the first character (for cases where we don't want to match the
" leading character: ", #, etc)
let l:first = strpart(a:base, 0, 1)
let l:rest = strpart(a:base, 1)
if l:partial_line =~# '^\d\d\d\d\(-\|/\)\d\d\1\d\d event $' && l:first ==# '"'
return beancountcomplete#complete_basic(b:beancount_events, l:rest, '"')
endif
let l:two_tokens = searchpos('\S\+\s', 'bn', line('.'))[1]
let l:prev_token = strpart(getline('.'), l:two_tokens, getpos('.')[2] - l:two_tokens)
" Match curriences if previous token is number
if l:prev_token =~# '^\d\+\([\.,]\d\+\)*'
call beancountcomplete#load_currencies()
return beancountcomplete#complete_basic(b:beancount_currencies, a:base, '')
endif
if l:first ==# '#'
call beancountcomplete#load_tags()
return beancountcomplete#complete_basic(b:beancount_tags, l:rest, '#')
elseif l:first ==# '^'
call beancountcomplete#load_links()
return beancountcomplete#complete_basic(b:beancount_links, l:rest, '^')
elseif l:first ==# '"'
call beancountcomplete#load_payees()
return beancountcomplete#complete_basic(b:beancount_payees, l:rest, '"')
else
call beancountcomplete#load_accounts()
return beancountcomplete#complete_account(a:base)
endif
endfunction
function! beancountcomplete#get_root() abort
if exists('b:beancount_root')
return b:beancount_root
endif
return expand('%')
endfunction
function! beancountcomplete#load_everything() abort
if s:using_python3 && !exists('b:beancount_loaded')
let l:root = beancountcomplete#get_root()
python3 << EOF
import vim
from beancount import loader
from beancount.core import data
accounts = set()
currencies = set()
events = set()
links = set()
payees = set()
tags = set()
entries, errors, options_map = loader.load_file(vim.eval('l:root'))
for index, entry in enumerate(entries):
if isinstance(entry, data.Open):
accounts.add(entry.account)
if entry.currencies:
currencies.update(entry.currencies)
elif isinstance(entry, data.Commodity):
currencies.add(entry.currency)
elif isinstance(entry, data.Event):
events.add(entry.type)
elif isinstance(entry, data.Transaction):
if entry.tags:
tags.update(entry.tags)
if entry.links:
links.update(entry.links)
if entry.payee:
payees.add(entry.payee)
vim.bindeval('b:')['beancount_accounts'] = sorted(accounts)
vim.bindeval('b:')['beancount_currencies'] = sorted(currencies)
vim.bindeval('b:')['beancount_events'] = sorted(events)
vim.bindeval('b:')['beancount_links'] = sorted(links)
vim.bindeval('b:')['beancount_payees'] = sorted(payees)
vim.bindeval('b:')['beancount_tags'] = sorted(tags)
vim.bindeval('b:')['beancount_loaded'] = 1
EOF
endif
endfunction
function! beancountcomplete#load_accounts() abort
if !s:using_python3 && !exists('b:beancount_accounts')
let l:root = beancountcomplete#get_root()
let b:beancount_accounts = beancountcomplete#query_single(l:root, 'select distinct account;')
endif
endfunction
function! beancountcomplete#load_tags() abort
if !s:using_python3 && !exists('b:beancount_tags')
let l:root = beancountcomplete#get_root()
let b:beancount_tags = beancountcomplete#query_single(l:root, 'select distinct tags;')
endif
endfunction
function! beancountcomplete#load_links() abort
if !s:using_python3 && !exists('b:beancount_links')
let l:root = beancountcomplete#get_root()
let b:beancount_links = beancountcomplete#query_single(l:root, 'select distinct links;')
endif
endfunction
function! beancountcomplete#load_currencies() abort
if !s:using_python3 && !exists('b:beancount_currencies')
let l:root = beancountcomplete#get_root()
let b:beancount_currencies = beancountcomplete#query_single(l:root, 'select distinct currency;')
endif
endfunction
function! beancountcomplete#load_payees() abort
if !s:using_python3 && !exists('b:beancount_payees')
let l:root = beancountcomplete#get_root()
let b:beancount_payees = beancountcomplete#query_single(l:root, 'select distinct payee;')
endif
endfunction
" General completion function
function! beancountcomplete#complete_basic(input, base, prefix) abort
let l:matches = filter(copy(a:input), 's:startswith(v:val, a:base)')
return map(l:matches, 'a:prefix . v:val')
endfunction
" Complete account name.
function! beancountcomplete#complete_account(base) abort
if g:beancount_account_completion ==? 'chunks'
let l:pattern = '^\V' . substitute(a:base, ':', '\\[^:]\\*:', 'g') . '\[^:]\*'
else
let l:pattern = '^\V\.\*' . substitute(a:base, ':', '\\.\\*:\\.\\*', 'g') . '\.\*'
endif
let l:matches = []
let l:index = -1
while 1
let l:index = match(b:beancount_accounts, l:pattern, l:index + 1)
if l:index == -1 | break | endif
call add(l:matches, matchstr(b:beancount_accounts[l:index], l:pattern))
endwhile
if g:beancount_detailed_first
let l:matches = reverse(sort(l:matches, 's:sort_accounts_by_depth'))
endif
return l:matches
endfunction
function! beancountcomplete#query_single(root_file, query) abort
if s:using_python3
python3 << EOF
import vim
import subprocess
# We intentionally want to ignore stderr so it doesn't mess up our query processing
output = subprocess.check_output(
['bean-query', vim.eval('a:root_file'), vim.eval('a:query')],
stderr=subprocess.DEVNULL,
text=True,
).splitlines()
output = output[2:]
result_list = sorted(y for y in (x.strip() for x in output) if y)
EOF
return py3eval('result_list')
else
return []
endif
endfunction

View File

@@ -0,0 +1,22 @@
" Vim compiler file
" Compiler: bean-check
" Maintainer: Nathan Grigg
" Latest Revision: 2017-03-20
if exists('g:current_compiler')
finish
endif
let g:current_compiler = 'bean_check'
let s:cpo_save = &cpoptions
set cpoptions-=C
CompilerSet makeprg=bean-check\ %
" File:line: message
" Skip blank lines and indented lines.
CompilerSet errorformat=%-G
CompilerSet errorformat+=%f:%l:\ %m
CompilerSet errorformat+=%-G\ %.%#
let &cpoptions = s:cpo_save
unlet s:cpo_save

View File

@@ -446,6 +446,65 @@ Support for features specific to GNU Awk, like @include, can be enabled by
setting: >
:let g:awk_is_gawk = 1
BEANCOUNT *ft-beancount-plugin*
Beancount omni-completion |compl-omni| is provided by beancountcomplete.vim,
if enabled with |g:beancount_completion_enable|.
To enable completion of account names, set: >
let g:beancount_completion_enable = 1
< Note enabling this may cause beancount to load additional plugin files.
Only enable for code you trust.
Variables:
*g:beancount_account_completion*
Can be either "default" or "chunks".
Default value: "default"
*g:beancount_completion_enable*
Enable omni-completion |compl-omni| for accounts.
Default value: 0
*g:beancount_detailed_first*
If non-zero, accounts higher down the hierarchy will be
listed first as completions.
Default value: 0
*g:beancount_separator_col*
The column that the decimal separator is aligned to.
Default value: 50
*b:beancount_root*
Set the root Beancount file. This is used to gather
values for the completion.
If not set, the current file will be used.
Default value: not set
Commands:
:AlignCommodity Adds spaces between an account and commodity so that the
decimal points of the commodities all occur in the column
given by |g:beancount_separator_col|. If an amount has no
decimal point, the imaginary decimal point to the right
of the least significant digit will align.
The command acts on a range, with the default being the
current line. If the cursor happens to be inside that
range and to the right of the account name, the cursor
will be pushed to the right the appropriate amount, so
that it remains on the same character.
The script assumes the use of spaces for alignment. It
does not understand tabs.
:GetContext Uses bean-doctor context to display the context of the
current line.
CHANGELOG *ft-changelog-plugin*

View File

@@ -0,0 +1,35 @@
if exists('b:did_ftplugin')
finish
endif
let b:did_ftplugin = 1
let b:undo_ftplugin = 'setlocal foldmethod< comments< commentstring< omnifunc<'
let b:undo_ftplugin .= '| delc -buffer AlignCommodity'
let b:undo_ftplugin .= '| delc -buffer GetContext'
setl foldmethod=syntax
setl comments=b:;
setl commentstring=;\ %s
compiler bean_check
" This variable customizes the behavior of the AlignCommodity command.
if !exists('g:beancount_separator_col')
let g:beancount_separator_col = 50
endif
if !exists('g:beancount_account_completion')
let g:beancount_account_completion = 'default'
endif
if !exists('g:beancount_detailed_first')
let g:beancount_detailed_first = 0
endif
command! -buffer -range AlignCommodity
\ :call beancount#align_commodity(<line1>, <line2>)
command! -buffer -range GetContext
\ :call beancount#get_context()
" Omnifunc for account completion.
if get(g:, 'beancount_completion_enable', 0)
setl omnifunc=beancountcomplete#complete
endif

View File

@@ -0,0 +1,51 @@
" Vim indent file
" Language: beancount
" Maintainer: Nathan Grigg
" Latest Revision: 2017-03-20
if exists('b:did_indent')
finish
endif
let b:did_indent = 1
setlocal indentexpr=GetBeancountIndent(v:lnum)
let b:undo_indent = "setl inde<"
if exists('*GetBeancountIndent')
finish
endif
function! s:IsDirective(str)
return a:str =~# '\v^\s*(\d{4}-\d{2}-\d{2}|pushtag|poptag|option|plugin|include)'
endfunction
function! s:IsPosting(str)
return a:str =~# '\v^\s*[A-Z]\w+:'
endfunction
function! s:IsMetadata(str)
return a:str =~# '\v^\s*[a-z][a-zA-Z0-9\-_]+:'
endfunction
function! s:IsTransaction(str)
" The final \S represents the flag (e.g. * or !).
return a:str =~# '\v^\s*\d{4}-\d{2}-\d{2}\s+(txn\s+)?\S(\s|$)'
endfunction
function GetBeancountIndent(line_num)
let l:this_line = getline(a:line_num)
let l:prev_line = getline(a:line_num - 1)
" Don't touch comments
if l:this_line =~# '\v^\s*;' | return -1 | endif
" This is a new directive or previous line is blank.
if l:prev_line =~# '^\s*$' || s:IsDirective(l:this_line) | return 0 | endif
" Previous line is transaction or this is a posting.
if s:IsTransaction(l:prev_line) || s:IsPosting(l:this_line) | return &shiftwidth | endif
if s:IsMetadata(l:this_line)
let l:this_indent = indent(a:line_num - 1)
if ! s:IsMetadata(l:prev_line) | let l:this_indent += &shiftwidth | endif
return l:this_indent
endif
return -1
endfunction

View File

@@ -0,0 +1,94 @@
" Vim syntax file
" Language: beancount
" Maintainer: Nathan Grigg
" Latest Revision: 2024-11-25
if exists("b:current_syntax")
finish
endif
syntax clear
" Basics.
syn region beanComment start="\s*;" end="$" keepend contains=beanMarker
syn match beanMarker "\v(\{\{\{|\}\}\})\d?" contained
syn region beanString start='"' skip='\\"' end='"' contained
syn match beanAmount "\v[-+]?[[:digit:].,]+" nextgroup=beanCurrency contained
\ skipwhite
syn match beanCurrency "\v\w+" contained
" Account name: alphanumeric with at least one colon.
syn match beanAccount "\v[[:alnum:]]+:[-[:alnum:]:]+" contained
syn match beanTag "\v#[-[:alnum:]]+" contained
syn match beanLink "\v\^\S+" contained
" We must require a space after the flag because you can have flags per
" transaction leg, and the letter-based flags might get confused with the
" start of an account name.
syn match beanFlag "\v[*!&#?%PSTCURM]\s\@=" contained
" Most directives start with a date.
syn match beanDate "^\v\d{4}[-/]\d{2}[-/]\d{2}" skipwhite
\ nextgroup=beanOpen,beanTxn,beanClose,beanCommodity,beanNote,beanBalance,beanEvent,beanPad,beanPrice
" Options and events have two string arguments. The first, we are matching as
" beanOptionTitle and the second as a regular string.
syn region beanOption matchgroup=beanKeyword start="^option" end="$"
\ keepend contains=beanOptionTitle,beanComment
syn region beanOption matchgroup=beanKeyword start="^plugin" end="$"
\ keepend contains=beanString,beanComment
syn region beanInclude matchgroup=beanKeyword start="^include" end="$"
\ keepend contains=beanString,beanComment
syn region beanEvent matchgroup=beanKeyword start="event" end="$" contained
\ keepend contains=beanOptionTitle,beanComment
syn region beanOptionTitle start='"' skip='\\"' end='"' contained
\ nextgroup=beanString skipwhite
syn region beanOpen matchgroup=beanKeyword start="open" end="$" keepend
\ contained contains=beanAccount,beanCurrency,beanComment
syn region beanClose matchgroup=beanKeyword start="close" end="$" keepend
\ contained contains=beanAccount,beanComment
syn region beanCommodity matchgroup=beanKeyword start="commodity" end="$" keepend
\ contained contains=beanCurrency,beanComment
syn region beanNote matchgroup=beanKeyword start="\vnote|document" end="$"
\ keepend contains=beanAccount,beanString,beanComment contained
syn region beanBalance matchgroup=beanKeyword start="balance" end="$" contained
\ keepend contains=beanAccount,beanAmount,beanComment
syn region beanPrice matchgroup=beanKeyword start="price" end="$" contained
\ keepend contains=beanCurrency,beanAmount
syn region beanPushTag matchgroup=beanKeyword start="\v^(push|pop)tag" end="$"
\ keepend contains=beanTag
syn region beanPad matchgroup=beanKeyword start="pad" end="$" contained
\ keepend contains=beanAccount,beanComment
syn region beanTxn matchgroup=beanKeyword start="\v\s+(txn|[*!&#?%PSTCURM])" skip="^\s"
\ end="^" keepend contained fold
\ contains=beanString,beanPost,beanComment,beanTag,beanLink,beanMeta
syn region beanPost start="^\v\C\s+(([*!&#?%PSTCURM]\s+)?[A-Z])@=" end="$"
\ contains=beanFlag,beanAccount,beanAmount,beanComment,beanCost,beanPrice
syn region beanMeta matchgroup=beanTag start="^\v\C\s+[a-z][-_a-zA-Z0-9]*:(\s|$)@=" end="$"
syn region beanCost start="{" end="}" contains=beanAmount contained
syn match beanPrice "\V@@\?" nextgroup=beanAmount contained
syn region beanHashHeaderFold
\ start="^\z(#\+\)"
\ skip="^\s*\z1#\+"
\ end="^\(#\)\@="
\ fold contains=TOP
syn region beanStarHeaderFold
\ start="^\z(\*\+\)"
\ skip="^\s*\z1\*\+"
\ end="^\(\*\)\@="
\ fold contains=TOP
highlight default link beanKeyword Keyword
highlight default link beanOptionTitle Keyword
highlight default link beanDate Keyword
highlight default link beanString String
highlight default link beanComment Comment
highlight default link beanAccount Identifier
highlight default link beanAmount Number
highlight default link beanCurrency Number
highlight default link beanCost Number
highlight default link beanPrice Number
highlight default link beanTag Tag
highlight default link beanLink Comment
highlight default link beanMeta Special
highlight default link beanFlag Keyword

View File

@@ -3,6 +3,7 @@
" Maintainer: KELEMEN Peter <Peter dot Kelemen at cern dot ch>
" Last Updates: Anton Shestakov, Hong Xu
" Last Change: 2015 Feb 10
" 2026 Jun 13 by Vim project: add smtp_destination_rate_delay #20505
" Version: 0.40
" URL: http://cern.ch/fuji/vim/syntax/pfmain.vim
" Comment: Based on Postfix 2.12/3.0 postconf.5.html.
@@ -497,6 +498,7 @@ syntax keyword pfmainConf smtp_defer_if_no_mx_address_found
syntax keyword pfmainConf smtp_delivery_status_filter
syntax keyword pfmainConf smtp_destination_concurrency_limit
syntax keyword pfmainConf smtp_destination_recipient_limit
syntax keyword pfmainConf smtp_destination_rate_delay
syntax keyword pfmainConf smtp_discard_ehlo_keyword_address_maps
syntax keyword pfmainConf smtp_discard_ehlo_keywords
syntax keyword pfmainConf smtp_dns_reply_filter
@@ -1290,6 +1292,7 @@ syntax match pfmainRef "$\<smtp_defer_if_no_mx_address_found\>"
syntax match pfmainRef "$\<smtp_delivery_status_filter\>"
syntax match pfmainRef "$\<smtp_destination_concurrency_limit\>"
syntax match pfmainRef "$\<smtp_destination_recipient_limit\>"
syntax match pfmainRef "$\<smtp_destination_rate_delay\>"
syntax match pfmainRef "$\<smtp_discard_ehlo_keyword_address_maps\>"
syntax match pfmainRef "$\<smtp_discard_ehlo_keywords\>"
syntax match pfmainRef "$\<smtp_dns_reply_filter\>"