mirror of
https://github.com/sheerun/vim-polyglot.git
synced 2025-11-09 12:03:53 -05:00
Remove some custom dirs config
This commit is contained in:
@@ -79,13 +79,13 @@ If you need full functionality of any plugin, please use it directly with your p
|
|||||||
- [ferm](https://github.com/vim-scripts/ferm.vim) (syntax)
|
- [ferm](https://github.com/vim-scripts/ferm.vim) (syntax)
|
||||||
- [fish](https://github.com/georgewitteman/vim-fish) (syntax, indent, compiler, autoload, ftplugin)
|
- [fish](https://github.com/georgewitteman/vim-fish) (syntax, indent, compiler, autoload, ftplugin)
|
||||||
- [flatbuffers](https://github.com/dcharbon/vim-flatbuffers) (syntax)
|
- [flatbuffers](https://github.com/dcharbon/vim-flatbuffers) (syntax)
|
||||||
- [fsharp](https://github.com/ionide/Ionide-vim) (syntax, indent)
|
- [fsharp](https://github.com/ionide/Ionide-vim) (syntax, indent, autoload)
|
||||||
- [gdscript](https://github.com/calviken/vim-gdscript3) (syntax, indent)
|
- [gdscript](https://github.com/calviken/vim-gdscript3) (syntax, indent)
|
||||||
- [git](https://github.com/tpope/vim-git) (syntax, indent, ftplugin)
|
- [git](https://github.com/tpope/vim-git) (syntax, indent, ftplugin)
|
||||||
- [glsl](https://github.com/tikhomirov/vim-glsl) (syntax, indent)
|
- [glsl](https://github.com/tikhomirov/vim-glsl) (syntax, indent)
|
||||||
- [gmpl](https://github.com/maelvalais/gmpl.vim) (syntax)
|
- [gmpl](https://github.com/maelvalais/gmpl.vim) (syntax)
|
||||||
- [gnuplot](https://github.com/vim-scripts/gnuplot-syntax-highlighting) (syntax)
|
- [gnuplot](https://github.com/vim-scripts/gnuplot-syntax-highlighting) (syntax)
|
||||||
- [go](https://github.com/fatih/vim-go) (syntax, compiler, indent)
|
- [go](https://github.com/fatih/vim-go) (syntax, indent, compiler)
|
||||||
- [gradle](https://github.com/tfnico/vim-gradle) (compiler)
|
- [gradle](https://github.com/tfnico/vim-gradle) (compiler)
|
||||||
- [graphql](https://github.com/jparise/vim-graphql) (syntax, indent, autoload, ftplugin, after)
|
- [graphql](https://github.com/jparise/vim-graphql) (syntax, indent, autoload, ftplugin, after)
|
||||||
- [haml](https://github.com/sheerun/vim-haml) (syntax, indent, compiler, ftplugin)
|
- [haml](https://github.com/sheerun/vim-haml) (syntax, indent, compiler, ftplugin)
|
||||||
@@ -112,7 +112,7 @@ If you need full functionality of any plugin, please use it directly with your p
|
|||||||
- [jsx](https://github.com/MaxMEllon/vim-jsx-pretty) (autoload, after)
|
- [jsx](https://github.com/MaxMEllon/vim-jsx-pretty) (autoload, after)
|
||||||
- [julia](https://github.com/JuliaEditorSupport/julia-vim) (syntax, indent, autoload, ftplugin)
|
- [julia](https://github.com/JuliaEditorSupport/julia-vim) (syntax, indent, autoload, ftplugin)
|
||||||
- [kotlin](https://github.com/udalov/kotlin-vim) (syntax, indent, ftplugin)
|
- [kotlin](https://github.com/udalov/kotlin-vim) (syntax, indent, ftplugin)
|
||||||
- [ledger](https://github.com/ledger/vim-ledger) (syntax, compiler, indent)
|
- [ledger](https://github.com/ledger/vim-ledger) (syntax, indent, compiler, autoload)
|
||||||
- [less](https://github.com/groenewege/vim-less) (syntax, indent, ftplugin)
|
- [less](https://github.com/groenewege/vim-less) (syntax, indent, ftplugin)
|
||||||
- [lilypond](https://github.com/anowlcalledjosh/vim-lilypond) (syntax, indent, compiler, ftplugin)
|
- [lilypond](https://github.com/anowlcalledjosh/vim-lilypond) (syntax, indent, compiler, ftplugin)
|
||||||
- [livescript](https://github.com/gkz/vim-ls) (syntax, indent, compiler, ftplugin)
|
- [livescript](https://github.com/gkz/vim-ls) (syntax, indent, compiler, ftplugin)
|
||||||
@@ -126,7 +126,7 @@ If you need full functionality of any plugin, please use it directly with your p
|
|||||||
- [meson](https://github.com/mesonbuild/meson) (syntax, indent, ftplugin)
|
- [meson](https://github.com/mesonbuild/meson) (syntax, indent, ftplugin)
|
||||||
- [moonscript](https://github.com/leafo/moonscript-vim) (syntax, indent, ftplugin)
|
- [moonscript](https://github.com/leafo/moonscript-vim) (syntax, indent, ftplugin)
|
||||||
- [nginx](https://github.com/chr4/nginx.vim) (syntax, indent, ftplugin)
|
- [nginx](https://github.com/chr4/nginx.vim) (syntax, indent, ftplugin)
|
||||||
- [nim](https://github.com/zah/nim.vim) (syntax, compiler, indent)
|
- [nim](https://github.com/zah/nim.vim) (syntax, indent, compiler, autoload)
|
||||||
- [nix](https://github.com/LnL7/vim-nix) (syntax, indent, compiler, ftplugin)
|
- [nix](https://github.com/LnL7/vim-nix) (syntax, indent, compiler, ftplugin)
|
||||||
- [objc](https://github.com/b4winckler/vim-objc) (ftplugin, syntax, indent)
|
- [objc](https://github.com/b4winckler/vim-objc) (ftplugin, syntax, indent)
|
||||||
- [ocaml](https://github.com/rgrinberg/vim-ocaml) (syntax, indent, compiler, ftplugin)
|
- [ocaml](https://github.com/rgrinberg/vim-ocaml) (syntax, indent, compiler, ftplugin)
|
||||||
|
|||||||
517
autoload/fsharp.vim
Normal file
517
autoload/fsharp.vim
Normal file
@@ -0,0 +1,517 @@
|
|||||||
|
if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'fsharp') == -1
|
||||||
|
|
||||||
|
" Vim autoload functions
|
||||||
|
|
||||||
|
if exists('g:loaded_autoload_fsharp')
|
||||||
|
finish
|
||||||
|
endif
|
||||||
|
let g:loaded_autoload_fsharp = 1
|
||||||
|
|
||||||
|
let s:cpo_save = &cpo
|
||||||
|
set cpo&vim
|
||||||
|
|
||||||
|
function! s:prompt(msg)
|
||||||
|
let height = &cmdheight
|
||||||
|
if height < 2
|
||||||
|
set cmdheight=2
|
||||||
|
endif
|
||||||
|
echom a:msg
|
||||||
|
let &cmdheight = height
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! s:PlainNotification(content)
|
||||||
|
return { 'Content': a:content }
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! s:TextDocumentIdentifier(path)
|
||||||
|
let usr_ss_opt = &shellslash
|
||||||
|
set shellslash
|
||||||
|
let uri = fnamemodify(a:path, ":p")
|
||||||
|
if uri[0] == "/"
|
||||||
|
let uri = "file://" . uri
|
||||||
|
else
|
||||||
|
let uri = "file:///" . uri
|
||||||
|
endif
|
||||||
|
let &shellslash = usr_ss_opt
|
||||||
|
return { 'Uri': uri }
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! s:Position(line, character)
|
||||||
|
return { 'Line': a:line, 'Character': a:character }
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! s:TextDocumentPositionParams(documentUri, line, character)
|
||||||
|
return {
|
||||||
|
\ 'TextDocument': s:TextDocumentIdentifier(a:documentUri),
|
||||||
|
\ 'Position': s:Position(a:line, a:character)
|
||||||
|
\ }
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! s:DocumentationForSymbolRequest(xmlSig, assembly)
|
||||||
|
return {
|
||||||
|
\ 'XmlSig': a:xmlSig,
|
||||||
|
\ 'Assembly': a:assembly
|
||||||
|
\ }
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! s:ProjectParms(projectUri)
|
||||||
|
return { 'Project': s:TextDocumentIdentifier(a:projectUri) }
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! s:WorkspacePeekRequest(directory, deep, excludedDirs)
|
||||||
|
return {
|
||||||
|
\ 'Directory': fnamemodify(a:directory, ":p"),
|
||||||
|
\ 'Deep': a:deep,
|
||||||
|
\ 'ExcludedDirs': a:excludedDirs
|
||||||
|
\ }
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! s:WorkspaceLoadParms(files)
|
||||||
|
let prm = []
|
||||||
|
for file in a:files
|
||||||
|
call add(prm, s:TextDocumentIdentifier(file))
|
||||||
|
endfor
|
||||||
|
return { 'TextDocuments': prm }
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! s:FsdnRequest(query)
|
||||||
|
return { 'Query': a:query }
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! s:call(method, params, cont)
|
||||||
|
call LanguageClient#Call(a:method, a:params, a:cont)
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! s:signature(filePath, line, character, cont)
|
||||||
|
return s:call('fsharp/signature', s:TextDocumentPositionParams(a:filePath, a:line, a:character), a:cont)
|
||||||
|
endfunction
|
||||||
|
function! s:signatureData(filePath, line, character, cont)
|
||||||
|
return s:call('fsharp/signatureData', s:TextDocumentPositionParams(a:filePath, a:line, a:character), a:cont)
|
||||||
|
endfunction
|
||||||
|
function! s:lineLens(projectPath, cont)
|
||||||
|
return s:call('fsharp/lineLens', s:ProjectParms(a:projectPath), a:cont)
|
||||||
|
endfunction
|
||||||
|
function! s:compilerLocation(cont)
|
||||||
|
return s:call('fsharp/compilerLocation', {}, a:cont)
|
||||||
|
endfunction
|
||||||
|
function! s:compile(projectPath, cont)
|
||||||
|
return s:call('fsharp/compile', s:ProjectParms(a:projectPath), a:cont)
|
||||||
|
endfunction
|
||||||
|
function! s:workspacePeek(directory, depth, excludedDirs, cont)
|
||||||
|
return s:call('fsharp/workspacePeek', s:WorkspacePeekRequest(a:directory, a:depth, a:excludedDirs), a:cont)
|
||||||
|
endfunction
|
||||||
|
function! s:workspaceLoad(files, cont)
|
||||||
|
return s:call('fsharp/workspaceLoad', s:WorkspaceLoadParms(a:files), a:cont)
|
||||||
|
endfunction
|
||||||
|
function! s:project(projectPath, cont)
|
||||||
|
return s:call('fsharp/project', s:ProjectParms(a:projectPath), a:cont)
|
||||||
|
endfunction
|
||||||
|
function! s:fsdn(signature, cont)
|
||||||
|
return s:call('fsharp/fsdn', s:FsdnRequest(a:signature), a:cont)
|
||||||
|
endfunction
|
||||||
|
function! s:f1Help(filePath, line, character, cont)
|
||||||
|
return s:call('fsharp/f1Help', s:TextDocumentPositionParams(a:filePath, a:line, a:character), a:cont)
|
||||||
|
endfunction
|
||||||
|
function! fsharp#documentation(filePath, line, character, cont)
|
||||||
|
return s:call('fsharp/documentation', s:TextDocumentPositionParams(a:filePath, a:line, a:character), a:cont)
|
||||||
|
endfunction
|
||||||
|
function! s:documentationSymbol(xmlSig, assembly, cont)
|
||||||
|
return s:call('fsharp/documentationSymbol', s:DocumentationForSymbolRequest(a:xmlSig, a:assembly), a:cont)
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
" FSharpConfigDto from https://github.com/fsharp/FsAutoComplete/blob/master/src/FsAutoComplete/LspHelpers.fs
|
||||||
|
"
|
||||||
|
" * The following options seems not working with workspace/didChangeConfiguration
|
||||||
|
" since the initialization has already completed?
|
||||||
|
" 'AutomaticWorkspaceInit',
|
||||||
|
" 'WorkspaceModePeekDeepLevel',
|
||||||
|
"
|
||||||
|
" * Changes made to linter/unused analyzer settings seems not reflected after sending them to FSAC?
|
||||||
|
"
|
||||||
|
let s:config_keys_camel =
|
||||||
|
\ [
|
||||||
|
\ {'key': 'AutomaticWorkspaceInit', 'default': 1},
|
||||||
|
\ {'key': 'WorkspaceModePeekDeepLevel', 'default': 2},
|
||||||
|
\ {'key': 'ExcludeProjectDirectories', 'default': []},
|
||||||
|
\ {'key': 'keywordsAutocomplete', 'default': 1},
|
||||||
|
\ {'key': 'ExternalAutocomplete', 'default': 0},
|
||||||
|
\ {'key': 'Linter', 'default': 1},
|
||||||
|
\ {'key': 'UnionCaseStubGeneration', 'default': 1},
|
||||||
|
\ {'key': 'UnionCaseStubGenerationBody'},
|
||||||
|
\ {'key': 'RecordStubGeneration', 'default': 1},
|
||||||
|
\ {'key': 'RecordStubGenerationBody'},
|
||||||
|
\ {'key': 'InterfaceStubGeneration', 'default': 1},
|
||||||
|
\ {'key': 'InterfaceStubGenerationObjectIdentifier', 'default': 'this'},
|
||||||
|
\ {'key': 'InterfaceStubGenerationMethodBody'},
|
||||||
|
\ {'key': 'UnusedOpensAnalyzer', 'default': 1},
|
||||||
|
\ {'key': 'UnusedDeclarationsAnalyzer', 'default': 1},
|
||||||
|
\ {'key': 'SimplifyNameAnalyzer', 'default': 0},
|
||||||
|
\ {'key': 'ResolveNamespaces', 'default': 1},
|
||||||
|
\ {'key': 'EnableReferenceCodeLens', 'default': 1},
|
||||||
|
\ {'key': 'EnableAnalyzers', 'default': 0},
|
||||||
|
\ {'key': 'AnalyzersPath'},
|
||||||
|
\ {'key': 'DisableInMemoryProjectReferences', 'default': 0},
|
||||||
|
\ {'key': 'LineLens', 'default': {'enabled': 'replaceCodeLens', 'prefix': '//'}},
|
||||||
|
\ {'key': 'UseSdkScripts', 'default': 1},
|
||||||
|
\ {'key': 'dotNetRoot'},
|
||||||
|
\ {'key': 'fsiExtraParameters', 'default': []},
|
||||||
|
\ ]
|
||||||
|
let s:config_keys = []
|
||||||
|
|
||||||
|
function! fsharp#toSnakeCase(str)
|
||||||
|
let sn = substitute(a:str, '\(\<\u\l\+\|\l\+\)\(\u\)', '\l\1_\l\2', 'g')
|
||||||
|
if sn == a:str | return tolower(a:str) | endif
|
||||||
|
return sn
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! s:buildConfigKeys()
|
||||||
|
if len(s:config_keys) == 0
|
||||||
|
for key_camel in s:config_keys_camel
|
||||||
|
let key = {}
|
||||||
|
let key.snake = fsharp#toSnakeCase(key_camel.key)
|
||||||
|
let key.camel = key_camel.key
|
||||||
|
if has_key(key_camel, 'default')
|
||||||
|
let key.default = key_camel.default
|
||||||
|
endif
|
||||||
|
call add(s:config_keys, key)
|
||||||
|
endfor
|
||||||
|
endif
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! g:fsharp#getServerConfig()
|
||||||
|
let fsharp = {}
|
||||||
|
call s:buildConfigKeys()
|
||||||
|
for key in s:config_keys
|
||||||
|
if exists('g:fsharp#' . key.snake)
|
||||||
|
let fsharp[key.camel] = g:fsharp#{key.snake}
|
||||||
|
elseif exists('g:fsharp#' . key.camel)
|
||||||
|
let fsharp[key.camel] = g:fsharp#{key.camel}
|
||||||
|
elseif has_key(key, 'default') && g:fsharp#use_recommended_server_config
|
||||||
|
let g:fsharp#{key.snake} = key.default
|
||||||
|
let fsharp[key.camel] = key.default
|
||||||
|
endif
|
||||||
|
endfor
|
||||||
|
return fsharp
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! g:fsharp#updateServerConfig()
|
||||||
|
let fsharp = fsharp#getServerConfig()
|
||||||
|
let settings = {'settings': {'FSharp': fsharp}}
|
||||||
|
call LanguageClient#Notify('workspace/didChangeConfiguration', settings)
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! s:findWorkspace(dir, cont)
|
||||||
|
let s:cont_findWorkspace = a:cont
|
||||||
|
function! s:callback_findWorkspace(result)
|
||||||
|
let result = a:result
|
||||||
|
let content = json_decode(result.result.content)
|
||||||
|
if len(content.Data.Found) < 1
|
||||||
|
return []
|
||||||
|
endif
|
||||||
|
let workspace = { 'Type': 'none' }
|
||||||
|
for found in content.Data.Found
|
||||||
|
if workspace.Type == 'none'
|
||||||
|
let workspace = found
|
||||||
|
elseif found.Type == 'solution'
|
||||||
|
if workspace.Type == 'project'
|
||||||
|
let workspace = found
|
||||||
|
else
|
||||||
|
let curLen = len(workspace.Data.Items)
|
||||||
|
let newLen = len(found.Data.Items)
|
||||||
|
if newLen > curLen
|
||||||
|
let workspace = found
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
endfor
|
||||||
|
if workspace.Type == 'solution'
|
||||||
|
call s:cont_findWorkspace([workspace.Data.Path])
|
||||||
|
else
|
||||||
|
call s:cont_findWorkspace(workspace.Data.Fsprojs)
|
||||||
|
endif
|
||||||
|
endfunction
|
||||||
|
call s:workspacePeek(a:dir, g:fsharp#workspace_mode_peek_deep_level, g:fsharp#exclude_project_directories, function("s:callback_findWorkspace"))
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
let s:workspace = []
|
||||||
|
|
||||||
|
function! s:load(arg)
|
||||||
|
let s:loading_workspace = a:arg
|
||||||
|
function! s:callback_load(_)
|
||||||
|
echo "[FSAC] Workspace loaded: " . join(s:loading_workspace, ', ')
|
||||||
|
let s:workspace = s:workspace + s:loading_workspace
|
||||||
|
endfunction
|
||||||
|
call s:workspaceLoad(a:arg, function("s:callback_load"))
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! fsharp#loadProject(...)
|
||||||
|
let prjs = []
|
||||||
|
for proj in a:000
|
||||||
|
call add(prjs, fnamemodify(proj, ':p'))
|
||||||
|
endfor
|
||||||
|
call s:load(prjs)
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! fsharp#loadWorkspaceAuto()
|
||||||
|
if &ft == 'fsharp'
|
||||||
|
call fsharp#updateServerConfig()
|
||||||
|
if g:fsharp#automatic_workspace_init
|
||||||
|
echom "[FSAC] Loading workspace..."
|
||||||
|
let bufferDirectory = fnamemodify(resolve(expand('%:p')), ':h')
|
||||||
|
call s:findWorkspace(bufferDirectory, function("s:load"))
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! fsharp#reloadProjects()
|
||||||
|
if len(s:workspace) > 0
|
||||||
|
function! s:callback_reloadProjects(_)
|
||||||
|
call s:prompt("[FSAC] Workspace reloaded.")
|
||||||
|
endfunction
|
||||||
|
call s:workspaceLoad(s:workspace, function("s:callback_reloadProjects"))
|
||||||
|
else
|
||||||
|
echom "[FSAC] Workspace is empty"
|
||||||
|
endif
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! fsharp#OnFSProjSave()
|
||||||
|
if &ft == "fsharp_project" && exists('g:fsharp#automatic_reload_workspace') && g:fsharp#automatic_reload_workspace
|
||||||
|
call fsharp#reloadProjects()
|
||||||
|
endif
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! fsharp#showSignature()
|
||||||
|
function! s:callback_showSignature(result)
|
||||||
|
let result = a:result
|
||||||
|
if exists('result.result.content')
|
||||||
|
let content = json_decode(result.result.content)
|
||||||
|
if exists('content.Data')
|
||||||
|
echom substitute(content.Data, '\n\+$', ' ', 'g')
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
endfunction
|
||||||
|
call s:signature(expand('%:p'), line('.') - 1, col('.') - 1, function("s:callback_showSignature"))
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! fsharp#OnCursorMove()
|
||||||
|
if g:fsharp#show_signature_on_cursor_move
|
||||||
|
call fsharp#showSignature()
|
||||||
|
endif
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! fsharp#showF1Help()
|
||||||
|
let result = s:f1Help(expand('%:p'), line('.') - 1, col('.') - 1)
|
||||||
|
echo result
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! fsharp#showTooltip()
|
||||||
|
function! s:callback_showTooltip(result)
|
||||||
|
let result = a:result
|
||||||
|
if exists('result.result.content')
|
||||||
|
let content = json_decode(result.result.content)
|
||||||
|
if exists('content.Data')
|
||||||
|
call LanguageClient#textDocument_hover()
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
endfunction
|
||||||
|
" show hover only if signature exists for the current position
|
||||||
|
call s:signature(expand('%:p'), line('.') - 1, col('.') - 1, function("s:callback_showTooltip"))
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
let s:script_root_dir = expand('<sfile>:p:h') . "/../"
|
||||||
|
let s:fsac = fnamemodify(s:script_root_dir . "fsac/fsautocomplete.dll", ":p")
|
||||||
|
let g:fsharp#languageserver_command =
|
||||||
|
\ ['dotnet', s:fsac,
|
||||||
|
\ '--background-service-enabled'
|
||||||
|
\ ]
|
||||||
|
|
||||||
|
function! s:download(branch)
|
||||||
|
echom "[FSAC] Downloading FSAC. This may take a while..."
|
||||||
|
let zip = s:script_root_dir . "fsac.zip"
|
||||||
|
call system(
|
||||||
|
\ 'curl -fLo ' . zip . ' --create-dirs ' .
|
||||||
|
\ '"https://ci.appveyor.com/api/projects/fsautocomplete/fsautocomplete/artifacts/bin/pkgs/fsautocomplete.netcore.zip?branch=' . a:branch . '"'
|
||||||
|
\ )
|
||||||
|
if v:shell_error == 0
|
||||||
|
call system('unzip -o -d ' . s:script_root_dir . "/fsac " . zip)
|
||||||
|
echom "[FSAC] Updated FsAutoComplete to version " . a:branch . ""
|
||||||
|
else
|
||||||
|
echom "[FSAC] Failed to update FsAutoComplete"
|
||||||
|
endif
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! fsharp#updateFSAC(...)
|
||||||
|
if len(a:000) == 0
|
||||||
|
let branch = "master"
|
||||||
|
else
|
||||||
|
let branch = a:000[0]
|
||||||
|
endif
|
||||||
|
call s:download(branch)
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
let s:fsi_buffer = -1
|
||||||
|
let s:fsi_job = -1
|
||||||
|
let s:fsi_width = 0
|
||||||
|
let s:fsi_height = 0
|
||||||
|
|
||||||
|
function! s:win_gotoid_safe(winid)
|
||||||
|
function! s:vimReturnFocus(window)
|
||||||
|
call win_gotoid(a:window)
|
||||||
|
redraw!
|
||||||
|
endfunction
|
||||||
|
if has('nvim')
|
||||||
|
call win_gotoid(a:winid)
|
||||||
|
else
|
||||||
|
call timer_start(1, { -> s:vimReturnFocus(a:winid) })
|
||||||
|
endif
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! s:get_fsi_command()
|
||||||
|
let cmd = g:fsharp#fsi_command
|
||||||
|
for prm in g:fsharp#fsi_extra_parameters
|
||||||
|
let cmd = cmd . " " . prm
|
||||||
|
endfor
|
||||||
|
return cmd
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! fsharp#openFsi(returnFocus)
|
||||||
|
if bufwinid(s:fsi_buffer) <= 0
|
||||||
|
let fsi_command = s:get_fsi_command()
|
||||||
|
" Neovim
|
||||||
|
if exists('*termopen') || exists('*term_start')
|
||||||
|
let current_win = win_getid()
|
||||||
|
execute g:fsharp#fsi_window_command
|
||||||
|
if s:fsi_width > 0 | execute 'vertical resize' s:fsi_width | endif
|
||||||
|
if s:fsi_height > 0 | execute 'resize' s:fsi_height | endif
|
||||||
|
" if window is closed but FSI is still alive then reuse it
|
||||||
|
if s:fsi_buffer >= 0 && bufexists(str2nr(s:fsi_buffer))
|
||||||
|
exec 'b' s:fsi_buffer
|
||||||
|
normal G
|
||||||
|
if !has('nvim') && mode() == 'n' | execute "normal A" | endif
|
||||||
|
if a:returnFocus | call s:win_gotoid_safe(current_win) | endif
|
||||||
|
" open FSI: Neovim
|
||||||
|
elseif has('nvim')
|
||||||
|
let s:fsi_job = termopen(fsi_command)
|
||||||
|
if s:fsi_job > 0
|
||||||
|
let s:fsi_buffer = bufnr("%")
|
||||||
|
else
|
||||||
|
close
|
||||||
|
echom "[FSAC] Failed to open FSI."
|
||||||
|
return -1
|
||||||
|
endif
|
||||||
|
" open FSI: Vim
|
||||||
|
else
|
||||||
|
let options = {
|
||||||
|
\ "term_name": "F# Interactive",
|
||||||
|
\ "curwin": 1,
|
||||||
|
\ "term_finish": "close"
|
||||||
|
\ }
|
||||||
|
let s:fsi_buffer = term_start(fsi_command, options)
|
||||||
|
if s:fsi_buffer != 0
|
||||||
|
if exists('*term_setkill') | call term_setkill(s:fsi_buffer, "term") | endif
|
||||||
|
let s:fsi_job = term_getjob(s:fsi_buffer)
|
||||||
|
else
|
||||||
|
close
|
||||||
|
echom "[FSAC] Failed to open FSI."
|
||||||
|
return -1
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
setlocal bufhidden=hide
|
||||||
|
normal G
|
||||||
|
if a:returnFocus | call s:win_gotoid_safe(current_win) | endif
|
||||||
|
return s:fsi_buffer
|
||||||
|
else
|
||||||
|
echom "[FSAC] Your Vim does not support terminal".
|
||||||
|
return 0
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
return s:fsi_buffer
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! fsharp#toggleFsi()
|
||||||
|
let fsiWindowId = bufwinid(s:fsi_buffer)
|
||||||
|
if fsiWindowId > 0
|
||||||
|
let current_win = win_getid()
|
||||||
|
call win_gotoid(fsiWindowId)
|
||||||
|
let s:fsi_width = winwidth('%')
|
||||||
|
let s:fsi_height = winheight('%')
|
||||||
|
close
|
||||||
|
call win_gotoid(current_win)
|
||||||
|
else
|
||||||
|
call fsharp#openFsi(0)
|
||||||
|
endif
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! fsharp#quitFsi()
|
||||||
|
if s:fsi_buffer >= 0 && bufexists(str2nr(s:fsi_buffer))
|
||||||
|
if has('nvim')
|
||||||
|
let winid = bufwinid(s:fsi_buffer)
|
||||||
|
if winid > 0 | execute "close " . winid | endif
|
||||||
|
call jobstop(s:fsi_job)
|
||||||
|
else
|
||||||
|
call job_stop(s:fsi_job, "term")
|
||||||
|
endif
|
||||||
|
let s:fsi_buffer = -1
|
||||||
|
let s:fsi_job = -1
|
||||||
|
endif
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! fsharp#resetFsi()
|
||||||
|
call fsharp#quitFsi()
|
||||||
|
return fsharp#openFsi(1)
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! fsharp#sendFsi(text)
|
||||||
|
if fsharp#openFsi(!g:fsharp#fsi_focus_on_send) > 0
|
||||||
|
" Neovim
|
||||||
|
if has('nvim')
|
||||||
|
call chansend(s:fsi_job, a:text . ";;". "\n")
|
||||||
|
" Vim 8
|
||||||
|
else
|
||||||
|
call term_sendkeys(s:fsi_buffer, a:text . ";;" . "\<cr>")
|
||||||
|
call term_wait(s:fsi_buffer)
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
" https://stackoverflow.com/a/6271254
|
||||||
|
function! s:get_visual_selection()
|
||||||
|
let [line_start, column_start] = getpos("'<")[1:2]
|
||||||
|
let [line_end, column_end] = getpos("'>")[1:2]
|
||||||
|
let lines = getline(line_start, line_end)
|
||||||
|
if len(lines) == 0
|
||||||
|
return ''
|
||||||
|
endif
|
||||||
|
let lines[-1] = lines[-1][: column_end - (&selection == 'inclusive' ? 1 : 2)]
|
||||||
|
let lines[0] = lines[0][column_start - 1:]
|
||||||
|
return lines
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! s:get_complete_buffer()
|
||||||
|
return join(getline(1, '$'), "\n")
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! fsharp#sendSelectionToFsi() range
|
||||||
|
let lines = s:get_visual_selection()
|
||||||
|
exec 'normal' len(lines) . 'j'
|
||||||
|
let text = join(lines, "\n")
|
||||||
|
return fsharp#sendFsi(text)
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! fsharp#sendLineToFsi()
|
||||||
|
let text = getline('.')
|
||||||
|
exec 'normal j'
|
||||||
|
return fsharp#sendFsi(text)
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! fsharp#sendAllToFsi()
|
||||||
|
let text = s:get_complete_buffer()
|
||||||
|
return fsharp#sendFsi(text)
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
let &cpo = s:cpo_save
|
||||||
|
unlet s:cpo_save
|
||||||
|
|
||||||
|
" vim: sw=4 et sts=4
|
||||||
|
|
||||||
|
endif
|
||||||
744
autoload/ledger.vim
Normal file
744
autoload/ledger.vim
Normal file
@@ -0,0 +1,744 @@
|
|||||||
|
if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'ledger') == -1
|
||||||
|
|
||||||
|
scriptencoding utf-8
|
||||||
|
" vim:ts=2:sw=2:sts=2:foldmethod=marker
|
||||||
|
function! ledger#transaction_state_toggle(lnum, ...) abort
|
||||||
|
if a:0 == 1
|
||||||
|
let chars = a:1
|
||||||
|
else
|
||||||
|
let chars = ' *'
|
||||||
|
endif
|
||||||
|
let trans = s:transaction.from_lnum(a:lnum)
|
||||||
|
if empty(trans) || has_key(trans, 'expr')
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
let old = has_key(trans, 'state') ? trans['state'] : ' '
|
||||||
|
let i = stridx(chars, old) + 1
|
||||||
|
let new = chars[i >= len(chars) ? 0 : i]
|
||||||
|
|
||||||
|
call trans.set_state(new)
|
||||||
|
|
||||||
|
call setline(trans['head'], trans.format_head())
|
||||||
|
endf
|
||||||
|
|
||||||
|
function! ledger#transaction_state_set(lnum, char) abort
|
||||||
|
" modifies or sets the state of the transaction at the cursor,
|
||||||
|
" removing the state altogether if a:char is empty
|
||||||
|
let trans = s:transaction.from_lnum(a:lnum)
|
||||||
|
if empty(trans) || has_key(trans, 'expr')
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
call trans.set_state(a:char)
|
||||||
|
|
||||||
|
call setline(trans['head'], trans.format_head())
|
||||||
|
endf
|
||||||
|
|
||||||
|
function! ledger#transaction_date_set(lnum, type, ...) abort
|
||||||
|
let time = a:0 == 1 ? a:1 : localtime()
|
||||||
|
let trans = s:transaction.from_lnum(a:lnum)
|
||||||
|
if empty(trans) || has_key(trans, 'expr')
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
let formatted = strftime(g:ledger_date_format, time)
|
||||||
|
if has_key(trans, 'date') && ! empty(trans['date'])
|
||||||
|
let date = split(trans['date'], '=')
|
||||||
|
else
|
||||||
|
let date = [formatted]
|
||||||
|
endif
|
||||||
|
|
||||||
|
if a:type =~? 'effective\|actual'
|
||||||
|
echoerr 'actual/effective arguments were replaced by primary/auxiliary'
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
if a:type ==? 'primary'
|
||||||
|
let date[0] = formatted
|
||||||
|
elseif a:type ==? 'auxiliary'
|
||||||
|
if time < 0
|
||||||
|
" remove auxiliary date
|
||||||
|
let date = [date[0]]
|
||||||
|
else
|
||||||
|
" set auxiliary date
|
||||||
|
if len(date) >= 2
|
||||||
|
let date[1] = formatted
|
||||||
|
else
|
||||||
|
call add(date, formatted)
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
elseif a:type ==? 'unshift'
|
||||||
|
let date = [formatted, date[0]]
|
||||||
|
endif
|
||||||
|
|
||||||
|
let trans['date'] = join(date[0:1], '=')
|
||||||
|
|
||||||
|
call setline(trans['head'], trans.format_head())
|
||||||
|
endf
|
||||||
|
|
||||||
|
" == get transactions ==
|
||||||
|
|
||||||
|
function! ledger#transaction_from_lnum(lnum) abort
|
||||||
|
return s:transaction.from_lnum(a:lnum)
|
||||||
|
endf
|
||||||
|
|
||||||
|
function! ledger#transactions(...) abort
|
||||||
|
if a:0 == 2
|
||||||
|
let lnum = a:1
|
||||||
|
let end = a:2
|
||||||
|
elseif a:0 == 0
|
||||||
|
let lnum = 1
|
||||||
|
let end = line('$')
|
||||||
|
else
|
||||||
|
throw 'wrong number of arguments for get_transactions()'
|
||||||
|
return []
|
||||||
|
endif
|
||||||
|
|
||||||
|
" safe view / position
|
||||||
|
let view = winsaveview()
|
||||||
|
let fe = &foldenable
|
||||||
|
set nofoldenable
|
||||||
|
|
||||||
|
let transactions = []
|
||||||
|
call cursor(lnum, 0)
|
||||||
|
while lnum && lnum < end
|
||||||
|
let trans = s:transaction.from_lnum(lnum)
|
||||||
|
if ! empty(trans)
|
||||||
|
call add(transactions, trans)
|
||||||
|
call cursor(trans['tail'], 0)
|
||||||
|
endif
|
||||||
|
let lnum = search('^[~=[:digit:]]', 'cW')
|
||||||
|
endw
|
||||||
|
|
||||||
|
" restore view / position
|
||||||
|
let &foldenable = fe
|
||||||
|
call winrestview(view)
|
||||||
|
|
||||||
|
return transactions
|
||||||
|
endf
|
||||||
|
|
||||||
|
" == transaction object implementation ==
|
||||||
|
|
||||||
|
let s:transaction = {} "{{{1
|
||||||
|
function! s:transaction.new() abort dict
|
||||||
|
return copy(s:transaction)
|
||||||
|
endf
|
||||||
|
|
||||||
|
function! s:transaction.from_lnum(lnum) abort dict "{{{2
|
||||||
|
let [head, tail] = s:get_transaction_extents(a:lnum)
|
||||||
|
if ! head
|
||||||
|
return {}
|
||||||
|
endif
|
||||||
|
|
||||||
|
let trans = copy(s:transaction)
|
||||||
|
let trans['head'] = head
|
||||||
|
let trans['tail'] = tail
|
||||||
|
|
||||||
|
" split off eventual comments at the end of line
|
||||||
|
let line = split(getline(head), '\ze\s*\%(\t\| \);', 1)
|
||||||
|
if len(line) > 1
|
||||||
|
let trans['appendix'] = join(line[1:], '')
|
||||||
|
endif
|
||||||
|
|
||||||
|
" parse rest of line
|
||||||
|
" FIXME (minor): will not preserve spacing (see 'join(parts)')
|
||||||
|
let parts = split(line[0], '\s\+')
|
||||||
|
if parts[0] ==# '~'
|
||||||
|
let trans['expr'] = join(parts[1:])
|
||||||
|
return trans
|
||||||
|
elseif parts[0] ==# '='
|
||||||
|
let trans['auto'] = join(parts[1:])
|
||||||
|
return trans
|
||||||
|
elseif parts[0] !~# '^\d'
|
||||||
|
" this case is avoided in s:get_transaction_extents(),
|
||||||
|
" but we'll check anyway.
|
||||||
|
return {}
|
||||||
|
endif
|
||||||
|
|
||||||
|
for part in parts
|
||||||
|
if ! has_key(trans, 'date') && part =~# '^\d'
|
||||||
|
let trans['date'] = part
|
||||||
|
elseif ! has_key(trans, 'code') && part =~# '^([^)]*)$'
|
||||||
|
let trans['code'] = part[1:-2]
|
||||||
|
elseif ! has_key(trans, 'state') && part =~# '^[[:punct:]]$'
|
||||||
|
" the first character by itself is assumed to be the state of the transaction.
|
||||||
|
let trans['state'] = part
|
||||||
|
else
|
||||||
|
" everything after date/code or state belongs to the description
|
||||||
|
break
|
||||||
|
endif
|
||||||
|
call remove(parts, 0)
|
||||||
|
endfor
|
||||||
|
|
||||||
|
let trans['description'] = join(parts)
|
||||||
|
return trans
|
||||||
|
endf "}}}
|
||||||
|
|
||||||
|
function! s:transaction.set_state(char) abort dict "{{{2
|
||||||
|
if has_key(self, 'state') && a:char =~# '^\s*$'
|
||||||
|
call remove(self, 'state')
|
||||||
|
else
|
||||||
|
let self['state'] = a:char
|
||||||
|
endif
|
||||||
|
endf "}}}
|
||||||
|
|
||||||
|
function! s:transaction.parse_body(...) abort dict "{{{2
|
||||||
|
if a:0 == 2
|
||||||
|
let head = a:1
|
||||||
|
let tail = a:2
|
||||||
|
elseif a:0 == 0
|
||||||
|
let head = self['head']
|
||||||
|
let tail = self['tail']
|
||||||
|
else
|
||||||
|
throw 'wrong number of arguments for parse_body()'
|
||||||
|
return []
|
||||||
|
endif
|
||||||
|
|
||||||
|
if ! head || tail <= head
|
||||||
|
return []
|
||||||
|
endif
|
||||||
|
|
||||||
|
let lnum = head
|
||||||
|
let tags = {}
|
||||||
|
let postings = []
|
||||||
|
while lnum <= tail
|
||||||
|
let line = split(getline(lnum), '\s*\%(\t\| \);', 1)
|
||||||
|
|
||||||
|
if line[0] =~# '^\s\+[^[:blank:];]'
|
||||||
|
" posting
|
||||||
|
let [state, rest] = matchlist(line[0], '^\s\+\([*!]\?\)\s*\(.*\)$')[1:2]
|
||||||
|
if rest =~# '\t\| '
|
||||||
|
let [account, amount] = matchlist(rest, '^\(.\{-}\)\%(\t\| \)\s*\(.\{-}\)\s*$')[1:2]
|
||||||
|
else
|
||||||
|
let amount = ''
|
||||||
|
let account = matchstr(rest, '^\s*\zs.\{-}\ze\s*$')
|
||||||
|
endif
|
||||||
|
call add(postings, {'account': account, 'amount': amount, 'state': state})
|
||||||
|
end
|
||||||
|
|
||||||
|
" where are tags to be stored?
|
||||||
|
if empty(postings)
|
||||||
|
" they belong to the transaction
|
||||||
|
let tag_container = tags
|
||||||
|
else
|
||||||
|
" they belong to last posting
|
||||||
|
if ! has_key(postings[-1], 'tags')
|
||||||
|
let postings[-1]['tags'] = {}
|
||||||
|
endif
|
||||||
|
let tag_container = postings[-1]['tags']
|
||||||
|
endif
|
||||||
|
|
||||||
|
let comment = join(line[1:], ' ;')
|
||||||
|
if comment =~# '^\s*:'
|
||||||
|
" tags without values
|
||||||
|
for t in s:findall(comment, ':\zs[^:[:blank:]]\([^:]*[^:[:blank:]]\)\?\ze:')
|
||||||
|
let tag_container[t] = ''
|
||||||
|
endfor
|
||||||
|
elseif comment =~# '^\s*[^:[:blank:]][^:]\+:'
|
||||||
|
" tag with value
|
||||||
|
let key = matchstr(comment, '^\s*\zs[^:]\+\ze:')
|
||||||
|
if ! empty(key)
|
||||||
|
let val = matchstr(comment, ':\s*\zs.*\ze\s*$')
|
||||||
|
let tag_container[key] = val
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
let lnum += 1
|
||||||
|
endw
|
||||||
|
return [tags, postings]
|
||||||
|
endf "}}}
|
||||||
|
|
||||||
|
function! s:transaction.format_head() abort dict "{{{2
|
||||||
|
if has_key(self, 'expr')
|
||||||
|
return '~ '.self['expr']
|
||||||
|
elseif has_key(self, 'auto')
|
||||||
|
return '= '.self['auto']
|
||||||
|
endif
|
||||||
|
|
||||||
|
let parts = []
|
||||||
|
if has_key(self, 'date') | call add(parts, self['date']) | endif
|
||||||
|
if has_key(self, 'state') | call add(parts, self['state']) | endif
|
||||||
|
if has_key(self, 'code') | call add(parts, '('.self['code'].')') | endif
|
||||||
|
if has_key(self, 'description') | call add(parts, self['description']) | endif
|
||||||
|
|
||||||
|
let line = join(parts)
|
||||||
|
if has_key(self, 'appendix') | let line .= self['appendix'] | endif
|
||||||
|
|
||||||
|
return line
|
||||||
|
endf "}}}
|
||||||
|
"}}}
|
||||||
|
|
||||||
|
" == helper functions ==
|
||||||
|
|
||||||
|
" get a list of declared accounts in the buffer
|
||||||
|
function! ledger#declared_accounts(...) abort
|
||||||
|
if a:0 == 2
|
||||||
|
let lnum = a:1
|
||||||
|
let lend = a:2
|
||||||
|
elseif a:0 == 0
|
||||||
|
let lnum = 1
|
||||||
|
let lend = line('$')
|
||||||
|
else
|
||||||
|
throw 'wrong number of arguments for ledger#declared_accounts()'
|
||||||
|
return []
|
||||||
|
endif
|
||||||
|
|
||||||
|
" save view / position
|
||||||
|
let view = winsaveview()
|
||||||
|
let fe = &foldenable
|
||||||
|
set nofoldenable
|
||||||
|
|
||||||
|
let accounts = []
|
||||||
|
call cursor(lnum, 0)
|
||||||
|
while 1
|
||||||
|
let lnum = search('^account\s', 'cW', lend)
|
||||||
|
if !lnum || lnum > lend
|
||||||
|
break
|
||||||
|
endif
|
||||||
|
|
||||||
|
" remove comments at the end and "account" at the front
|
||||||
|
let line = split(getline(lnum), '\s\+;')[0]
|
||||||
|
let line = matchlist(line, 'account\s\+\(.\+\)')[1]
|
||||||
|
|
||||||
|
if len(line) > 1
|
||||||
|
call add(accounts, line)
|
||||||
|
endif
|
||||||
|
|
||||||
|
call cursor(lnum+1,0)
|
||||||
|
endw
|
||||||
|
|
||||||
|
" restore view / position
|
||||||
|
let &foldenable = fe
|
||||||
|
call winrestview(view)
|
||||||
|
|
||||||
|
return accounts
|
||||||
|
endf
|
||||||
|
|
||||||
|
function! s:get_transaction_extents(lnum) abort
|
||||||
|
if ! (indent(a:lnum) || getline(a:lnum) =~# '^[~=[:digit:]]')
|
||||||
|
" only do something if lnum is in a transaction
|
||||||
|
return [0, 0]
|
||||||
|
endif
|
||||||
|
|
||||||
|
" safe view / position
|
||||||
|
let view = winsaveview()
|
||||||
|
let fe = &foldenable
|
||||||
|
set nofoldenable
|
||||||
|
|
||||||
|
call cursor(a:lnum, 0)
|
||||||
|
let head = search('^[~=[:digit:]]', 'bcnW')
|
||||||
|
let tail = search('^[^;[:blank:]]\S\+', 'nW')
|
||||||
|
let tail = tail > head ? tail - 1 : line('$')
|
||||||
|
|
||||||
|
" restore view / position
|
||||||
|
let &foldenable = fe
|
||||||
|
call winrestview(view)
|
||||||
|
|
||||||
|
return head ? [head, tail] : [0, 0]
|
||||||
|
endf
|
||||||
|
|
||||||
|
function! ledger#find_in_tree(tree, levels) abort
|
||||||
|
if empty(a:levels)
|
||||||
|
return []
|
||||||
|
endif
|
||||||
|
let results = []
|
||||||
|
let currentlvl = a:levels[0]
|
||||||
|
let nextlvls = a:levels[1:]
|
||||||
|
let branches = ledger#filter_items(keys(a:tree), currentlvl)
|
||||||
|
for branch in branches
|
||||||
|
let exact = empty(nextlvls)
|
||||||
|
call add(results, [branch, exact])
|
||||||
|
if ! empty(nextlvls)
|
||||||
|
for [result, exact] in ledger#find_in_tree(a:tree[branch], nextlvls)
|
||||||
|
call add(results, [branch.':'.result, exact])
|
||||||
|
endfor
|
||||||
|
endif
|
||||||
|
endfor
|
||||||
|
return results
|
||||||
|
endf
|
||||||
|
|
||||||
|
function! ledger#filter_items(list, keyword) abort
|
||||||
|
" return only those items that start with a specified keyword
|
||||||
|
return filter(copy(a:list), 'v:val =~ ''^\V'.substitute(a:keyword, '\\', '\\\\', 'g').'''')
|
||||||
|
endf
|
||||||
|
|
||||||
|
function! s:findall(text, rx) abort
|
||||||
|
" returns all the matches in a string,
|
||||||
|
" there will be overlapping matches according to :help match()
|
||||||
|
let matches = []
|
||||||
|
|
||||||
|
while 1
|
||||||
|
let m = matchstr(a:text, a:rx, 0, len(matches)+1)
|
||||||
|
if empty(m)
|
||||||
|
break
|
||||||
|
endif
|
||||||
|
|
||||||
|
call add(matches, m)
|
||||||
|
endw
|
||||||
|
|
||||||
|
return matches
|
||||||
|
endf
|
||||||
|
|
||||||
|
" Move the cursor to the specified column, filling the line with spaces if necessary.
|
||||||
|
" Ensure that at least min_spaces are added, and go to the end of the line if
|
||||||
|
" the line is already too long
|
||||||
|
function! s:goto_col(pos, min_spaces) abort
|
||||||
|
exec 'normal!' '$'
|
||||||
|
let diff = max([a:min_spaces, a:pos - virtcol('.')])
|
||||||
|
if diff > 0 | exec 'normal!' diff . 'a ' | endif
|
||||||
|
endf
|
||||||
|
|
||||||
|
" Return character position of decimal separator (multibyte safe)
|
||||||
|
function! s:decimalpos(expr) abort
|
||||||
|
let pos = match(a:expr, '\V' . g:ledger_decimal_sep)
|
||||||
|
if pos > 0
|
||||||
|
let pos = strchars(a:expr[:pos]) - 1
|
||||||
|
endif
|
||||||
|
return pos
|
||||||
|
endf
|
||||||
|
|
||||||
|
" Align the amount expression after an account name at the decimal point.
|
||||||
|
"
|
||||||
|
" This function moves the amount expression of a posting so that the decimal
|
||||||
|
" separator is aligned at the column specified by g:ledger_align_at.
|
||||||
|
"
|
||||||
|
" For example, after selecting:
|
||||||
|
"
|
||||||
|
" 2015/05/09 Some Payee
|
||||||
|
" Expenses:Other $120,23 ; Tags here
|
||||||
|
" Expenses:Something $-4,99
|
||||||
|
" Expenses:More ($12,34 + $16,32)
|
||||||
|
"
|
||||||
|
" :'<,'>call ledger#align_commodity() produces:
|
||||||
|
"
|
||||||
|
" 2015/05/09 Some Payee
|
||||||
|
" Expenses:Other $120,23 ; Tags here
|
||||||
|
" Expenses:Something $-4,99
|
||||||
|
" Expenses:More ($12,34 + $16,32)
|
||||||
|
"
|
||||||
|
function! ledger#align_commodity() abort
|
||||||
|
" Extract the part of the line after the account name (excluding spaces):
|
||||||
|
let l:line = getline('.')
|
||||||
|
let rhs = matchstr(l:line, '\m^\s\+[^;[:space:]].\{-}\(\t\| \)\s*\zs.*$')
|
||||||
|
if rhs !=# ''
|
||||||
|
" Remove everything after the account name (including spaces):
|
||||||
|
call setline('.', substitute(l:line, '\m^\s\+[^[:space:]].\{-}\zs\(\t\| \).*$', '', ''))
|
||||||
|
let pos = -1
|
||||||
|
if g:ledger_decimal_sep !=# ''
|
||||||
|
" Find the position of the first decimal separator:
|
||||||
|
let pos = s:decimalpos(rhs)
|
||||||
|
endif
|
||||||
|
if pos < 0
|
||||||
|
" Find the position after the first digits
|
||||||
|
let pos = matchend(rhs, '\m\d[^[:space:]]*')
|
||||||
|
endif
|
||||||
|
" Go to the column that allows us to align the decimal separator at g:ledger_align_at:
|
||||||
|
if pos > 0
|
||||||
|
call s:goto_col(g:ledger_align_at - pos - 1, 2)
|
||||||
|
else
|
||||||
|
call s:goto_col(g:ledger_align_at - strdisplaywidth(rhs) - 2, 2)
|
||||||
|
endif " Append the part of the line that was previously removed:
|
||||||
|
exe 'normal! a' . rhs
|
||||||
|
endif
|
||||||
|
endf
|
||||||
|
|
||||||
|
" Align the amount under the cursor and append/prepend the default currency.
|
||||||
|
function! ledger#align_amount_at_cursor() abort
|
||||||
|
" Select and cut text:
|
||||||
|
normal! viWd
|
||||||
|
" Find the position of the decimal separator
|
||||||
|
let pos = s:decimalpos(@") " Returns zero when the separator is the empty string
|
||||||
|
if pos <= 0
|
||||||
|
let pos = len(@")
|
||||||
|
endif
|
||||||
|
" Paste text at the correct column and append/prepend default commodity:
|
||||||
|
if g:ledger_commodity_before
|
||||||
|
call s:goto_col(g:ledger_align_at - pos - len(g:ledger_default_commodity) - len(g:ledger_commodity_sep) - 1, 2)
|
||||||
|
exe 'normal! a' . g:ledger_default_commodity . g:ledger_commodity_sep
|
||||||
|
normal! p
|
||||||
|
else
|
||||||
|
call s:goto_col(g:ledger_align_at - pos - 1, 2)
|
||||||
|
exe 'normal! pa' . g:ledger_commodity_sep . g:ledger_default_commodity
|
||||||
|
endif
|
||||||
|
endf
|
||||||
|
|
||||||
|
" Report generation {{{1
|
||||||
|
|
||||||
|
" Helper functions and variables {{{2
|
||||||
|
" Position of report windows
|
||||||
|
let s:winpos_map = {
|
||||||
|
\ 'T': 'to new', 't': 'abo new', 'B': 'bo new', 'b': 'bel new',
|
||||||
|
\ 'L': 'to vnew', 'l': 'abo vnew', 'R': 'bo vnew', 'r': 'bel vnew'
|
||||||
|
\ }
|
||||||
|
|
||||||
|
function! s:error_message(msg) abort
|
||||||
|
redraw " See h:echo-redraw
|
||||||
|
echohl ErrorMsg
|
||||||
|
echo "\r"
|
||||||
|
echomsg a:msg
|
||||||
|
echohl NONE
|
||||||
|
endf
|
||||||
|
|
||||||
|
function! s:warning_message(msg) abort
|
||||||
|
redraw " See h:echo-redraw
|
||||||
|
echohl WarningMsg
|
||||||
|
echo "\r"
|
||||||
|
echomsg a:msg
|
||||||
|
echohl NONE
|
||||||
|
endf
|
||||||
|
|
||||||
|
" Open the quickfix/location window when it is not empty,
|
||||||
|
" closes it if it is empty.
|
||||||
|
"
|
||||||
|
" Optional parameters:
|
||||||
|
" a:1 Quickfix window title.
|
||||||
|
" a:2 Message to show when the window is empty.
|
||||||
|
"
|
||||||
|
" Returns 0 if the quickfix window is empty, 1 otherwise.
|
||||||
|
function! s:quickfix_toggle(...) abort
|
||||||
|
if g:ledger_use_location_list
|
||||||
|
let l:list = 'l'
|
||||||
|
let l:open = (len(getloclist(winnr())) > 0)
|
||||||
|
else
|
||||||
|
let l:list = 'c'
|
||||||
|
let l:open = (len(getqflist()) > 0)
|
||||||
|
endif
|
||||||
|
|
||||||
|
if l:open
|
||||||
|
execute (g:ledger_qf_vertical ? 'vert' : 'botright') l:list.'open' g:ledger_qf_size
|
||||||
|
" Set local mappings to quit the quickfix window or lose focus.
|
||||||
|
nnoremap <silent> <buffer> <tab> <c-w><c-w>
|
||||||
|
execute 'nnoremap <silent> <buffer> q :' l:list.'close<CR>'
|
||||||
|
" Note that the following settings do not persist (e.g., when you close and re-open the quickfix window).
|
||||||
|
" See: https://superuser.com/questions/356912/how-do-i-change-the-quickix-title-status-bar-in-vim
|
||||||
|
if g:ledger_qf_hide_file
|
||||||
|
setl conceallevel=2
|
||||||
|
setl concealcursor=nc
|
||||||
|
syntax match qfFile /^[^|]*/ transparent conceal
|
||||||
|
endif
|
||||||
|
if a:0 > 0
|
||||||
|
let w:quickfix_title = a:1
|
||||||
|
endif
|
||||||
|
return 1
|
||||||
|
endif
|
||||||
|
|
||||||
|
execute l:list.'close'
|
||||||
|
call s:warning_message((a:0 > 1) ? a:2 : 'No results')
|
||||||
|
return 0
|
||||||
|
endf
|
||||||
|
|
||||||
|
" Populate a quickfix/location window with data. The argument must be a String
|
||||||
|
" or a List.
|
||||||
|
function! s:quickfix_populate(data) abort
|
||||||
|
" Note that cexpr/lexpr always uses the global value of errorformat
|
||||||
|
let l:efm = &errorformat " Save global errorformat
|
||||||
|
set errorformat=%EWhile\ parsing\ file\ \"%f\"\\,\ line\ %l:,%ZError:\ %m,%-C%.%#
|
||||||
|
set errorformat+=%tarning:\ \"%f\"\\,\ line\ %l:\ %m
|
||||||
|
" Format to parse command-line errors:
|
||||||
|
set errorformat+=Error:\ %m
|
||||||
|
" Format to parse reports:
|
||||||
|
set errorformat+=%f:%l\ %m
|
||||||
|
set errorformat+=%-G%.%#
|
||||||
|
execute (g:ledger_use_location_list ? 'l' : 'c').'getexpr' 'a:data'
|
||||||
|
let &errorformat = l:efm " Restore global errorformat
|
||||||
|
return
|
||||||
|
endf
|
||||||
|
|
||||||
|
" Build a ledger command to process the given file.
|
||||||
|
function! s:ledger_cmd(file, args) abort
|
||||||
|
let l:options = g:ledger_extra_options
|
||||||
|
if len(g:ledger_date_format) > 0 && !g:ledger_is_hledger
|
||||||
|
let l:options = join([l:options, '--date-format', g:ledger_date_format,
|
||||||
|
\ '--input-date-format', g:ledger_date_format])
|
||||||
|
endif
|
||||||
|
return join([g:ledger_bin, l:options, '-f', shellescape(expand(a:file)), a:args])
|
||||||
|
endf
|
||||||
|
" }}}
|
||||||
|
|
||||||
|
function! ledger#autocomplete_and_align() abort
|
||||||
|
if pumvisible()
|
||||||
|
return "\<c-n>"
|
||||||
|
endif
|
||||||
|
" Align an amount only if there is a digit immediately before the cursor and
|
||||||
|
" such digit is preceded by at least one space (the latter condition is
|
||||||
|
" necessary to avoid situations where a date starting at the first column is
|
||||||
|
" confused with a commodity to be aligned).
|
||||||
|
if match(getline('.'), '\s.*\d\%'.col('.').'c') > -1
|
||||||
|
normal! h
|
||||||
|
call ledger#align_amount_at_cursor()
|
||||||
|
return "\<c-o>A"
|
||||||
|
endif
|
||||||
|
return "\<c-x>\<c-o>"
|
||||||
|
endf
|
||||||
|
|
||||||
|
" Use current line as input to ledger entry and replace with output. If there
|
||||||
|
" are errors, they are echoed instead.
|
||||||
|
function! ledger#entry() abort
|
||||||
|
let l:output = systemlist(s:ledger_cmd(g:ledger_main, join(['entry', getline('.')])))
|
||||||
|
" Filter out warnings
|
||||||
|
let l:output = filter(l:output, "v:val !~? '^Warning: '")
|
||||||
|
" Errors may occur
|
||||||
|
if v:shell_error
|
||||||
|
echomsg join(l:output)
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
" Append output so we insert instead of overwrite, then delete line
|
||||||
|
call append('.', l:output)
|
||||||
|
normal! "_dd
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
" Run an arbitrary ledger command and show the output in a new buffer. If
|
||||||
|
" there are errors, no new buffer is opened: the errors are displayed in a
|
||||||
|
" quickfix window instead.
|
||||||
|
"
|
||||||
|
" Parameters:
|
||||||
|
" file The file to be processed.
|
||||||
|
" args A string of Ledger command-line arguments.
|
||||||
|
"
|
||||||
|
" Returns:
|
||||||
|
" Ledger's output as a String.
|
||||||
|
function! ledger#report(file, args) abort
|
||||||
|
let l:output = systemlist(s:ledger_cmd(a:file, a:args))
|
||||||
|
if v:shell_error " If there are errors, show them in a quickfix/location list.
|
||||||
|
call s:quickfix_populate(l:output)
|
||||||
|
call s:quickfix_toggle('Errors', 'Unable to parse errors')
|
||||||
|
endif
|
||||||
|
return l:output
|
||||||
|
endf
|
||||||
|
|
||||||
|
" Open the output of a Ledger's command in a new buffer.
|
||||||
|
"
|
||||||
|
" Parameters:
|
||||||
|
" report A String containing the output of a Ledger's command.
|
||||||
|
"
|
||||||
|
" Returns:
|
||||||
|
" 1 if a new buffer is created; 0 otherwise.
|
||||||
|
function! ledger#output(report) abort
|
||||||
|
if empty(a:report)
|
||||||
|
call s:warning_message('No results')
|
||||||
|
return 0
|
||||||
|
endif
|
||||||
|
" Open a new buffer to show Ledger's output.
|
||||||
|
execute get(s:winpos_map, g:ledger_winpos, 'bo new')
|
||||||
|
setlocal buftype=nofile bufhidden=wipe modifiable nobuflisted noswapfile nowrap
|
||||||
|
call append(0, a:report)
|
||||||
|
setlocal nomodifiable
|
||||||
|
" Set local mappings to quit window or lose focus.
|
||||||
|
nnoremap <silent> <buffer> <tab> <c-w><c-p>
|
||||||
|
nnoremap <silent> <buffer> q <c-w><c-p>@=winnr('#')<cr><c-w>c
|
||||||
|
" Add some coloring to the report
|
||||||
|
syntax match LedgerNumber /-\@1<!\d\+\([,.]\d\+\)*/
|
||||||
|
syntax match LedgerNegativeNumber /-\d\+\([,.]\d\+\)*/
|
||||||
|
syntax match LedgerImproperPerc /\d\d\d\+%/
|
||||||
|
return 1
|
||||||
|
endf
|
||||||
|
|
||||||
|
" Show an arbitrary register report in a quickfix list.
|
||||||
|
"
|
||||||
|
" Parameters:
|
||||||
|
" file The file to be processed
|
||||||
|
" args A string of Ledger command-line arguments.
|
||||||
|
function! ledger#register(file, args) abort
|
||||||
|
let l:cmd = s:ledger_cmd(a:file, join([
|
||||||
|
\ 'register',
|
||||||
|
\ "--format='" . g:ledger_qf_register_format . "'",
|
||||||
|
\ "--prepend-format='%(filename):%(beg_line) '",
|
||||||
|
\ a:args
|
||||||
|
\ ]))
|
||||||
|
call s:quickfix_populate(systemlist(l:cmd))
|
||||||
|
call s:quickfix_toggle('Register report')
|
||||||
|
endf
|
||||||
|
|
||||||
|
" Reconcile the given account.
|
||||||
|
" This function accepts a file path as a third optional argument.
|
||||||
|
" The default is to use the value of g:ledger_main.
|
||||||
|
"
|
||||||
|
" Parameters:
|
||||||
|
" file The file to be processed
|
||||||
|
" account An account name (String)
|
||||||
|
" target_amount The target amount (Float)
|
||||||
|
function! ledger#reconcile(file, account, target_amount) abort
|
||||||
|
let l:cmd = s:ledger_cmd(a:file, join([
|
||||||
|
\ 'register',
|
||||||
|
\ '--uncleared',
|
||||||
|
\ "--format='" . g:ledger_qf_reconcile_format . "'",
|
||||||
|
\ "--prepend-format='%(filename):%(beg_line) %(pending ? \"P\" : \"U\") '",
|
||||||
|
\ shellescape(a:account)
|
||||||
|
\ ]))
|
||||||
|
let l:file = expand(a:file) " Needed for #show_balance() later
|
||||||
|
call s:quickfix_populate(systemlist(l:cmd))
|
||||||
|
if s:quickfix_toggle('Reconcile ' . a:account, 'Nothing to reconcile')
|
||||||
|
let g:ledger_target_amount = a:target_amount
|
||||||
|
" Show updated account balance upon saving, as long as the quickfix window is open
|
||||||
|
augroup reconcile
|
||||||
|
autocmd!
|
||||||
|
execute "autocmd BufWritePost *.ldg,*.ledger call ledger#show_balance('" . l:file . "','" . a:account . "')"
|
||||||
|
autocmd BufWipeout <buffer> call <sid>finish_reconciling()
|
||||||
|
augroup END
|
||||||
|
" Add refresh shortcut
|
||||||
|
execute "nnoremap <silent> <buffer> <c-l> :<c-u>call ledger#reconcile('"
|
||||||
|
\ . l:file . "','" . a:account . "'," . string(a:target_amount) . ')<cr>'
|
||||||
|
call ledger#show_balance(l:file, a:account)
|
||||||
|
endif
|
||||||
|
endf
|
||||||
|
|
||||||
|
function! s:finish_reconciling() abort
|
||||||
|
unlet g:ledger_target_amount
|
||||||
|
augroup reconcile
|
||||||
|
autocmd!
|
||||||
|
augroup END
|
||||||
|
augroup! reconcile
|
||||||
|
endf
|
||||||
|
|
||||||
|
" Show the pending/cleared balance of an account.
|
||||||
|
" This function has an optional parameter:
|
||||||
|
"
|
||||||
|
" a:1 An account name
|
||||||
|
"
|
||||||
|
" If no account if given, the account in the current line is used.
|
||||||
|
function! ledger#show_balance(file, ...) abort
|
||||||
|
let l:account = a:0 > 0 && !empty(a:1) ? a:1 : matchstr(getline('.'), '\m\( \|\t\)\zs\S.\{-}\ze\( \|\t\|$\)')
|
||||||
|
if empty(l:account)
|
||||||
|
call s:error_message('No account found')
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
let l:cmd = s:ledger_cmd(a:file, join([
|
||||||
|
\ 'cleared',
|
||||||
|
\ shellescape(l:account),
|
||||||
|
\ '--empty',
|
||||||
|
\ '--collapse',
|
||||||
|
\ "--format='%(scrub(get_at(display_total, 0)))|%(scrub(get_at(display_total, 1)))|%(quantity(scrub(get_at(display_total, 1))))'",
|
||||||
|
\ (empty(g:ledger_default_commodity) ? '' : '-X ' . shellescape(g:ledger_default_commodity))
|
||||||
|
\ ]))
|
||||||
|
let l:output = systemlist(l:cmd)
|
||||||
|
" Errors may occur, for example, when the account has multiple commodities
|
||||||
|
" and g:ledger_default_commodity is empty.
|
||||||
|
if v:shell_error
|
||||||
|
call s:quickfix_populate(l:output)
|
||||||
|
call s:quickfix_toggle('Errors', 'Unable to parse errors')
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
let l:amounts = split(l:output[-1], '|')
|
||||||
|
redraw " Necessary in some cases to overwrite previous messages. See :h echo-redraw
|
||||||
|
if len(l:amounts) < 3
|
||||||
|
call s:error_message('Could not determine balance. Did you use a valid account?')
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
echo g:ledger_pending_string
|
||||||
|
echohl LedgerPending
|
||||||
|
echon l:amounts[0]
|
||||||
|
echohl NONE
|
||||||
|
echon ' ' g:ledger_cleared_string
|
||||||
|
echohl LedgerCleared
|
||||||
|
echon l:amounts[1]
|
||||||
|
echohl NONE
|
||||||
|
if exists('g:ledger_target_amount')
|
||||||
|
echon ' ' g:ledger_target_string
|
||||||
|
echohl LedgerTarget
|
||||||
|
echon printf('%.2f', (g:ledger_target_amount - str2float(l:amounts[2])))
|
||||||
|
echohl NONE
|
||||||
|
endif
|
||||||
|
endf
|
||||||
|
" }}}
|
||||||
|
|
||||||
|
endif
|
||||||
244
autoload/nim.vim
Normal file
244
autoload/nim.vim
Normal file
@@ -0,0 +1,244 @@
|
|||||||
|
if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'nim') == -1
|
||||||
|
|
||||||
|
let g:nim_log = []
|
||||||
|
let s:plugin_path = escape(expand('<sfile>:p:h'), '\')
|
||||||
|
|
||||||
|
if !exists("g:nim_caas_enabled")
|
||||||
|
let g:nim_caas_enabled = 0
|
||||||
|
endif
|
||||||
|
|
||||||
|
if !executable('nim')
|
||||||
|
echoerr "the Nim compiler must be in your system's PATH"
|
||||||
|
endif
|
||||||
|
|
||||||
|
if has("python3")
|
||||||
|
exe 'py3file ' . fnameescape(s:plugin_path) . '/nim_vim.py'
|
||||||
|
elseif has("python")
|
||||||
|
exe 'pyfile ' . fnameescape(s:plugin_path) . '/nim_vim.py'
|
||||||
|
endif
|
||||||
|
|
||||||
|
fun! nim#init()
|
||||||
|
let cmd = printf("nim --dump.format:json --verbosity:0 dump %s", s:CurrentNimFile())
|
||||||
|
let raw_dumpdata = system(cmd)
|
||||||
|
if !v:shell_error && expand("%:e") == "nim"
|
||||||
|
let false = 0 " Needed for eval of json
|
||||||
|
let true = 1 " Needed for eval of json
|
||||||
|
let dumpdata = eval(substitute(raw_dumpdata, "\n", "", "g"))
|
||||||
|
|
||||||
|
let b:nim_project_root = dumpdata['project_path']
|
||||||
|
let b:nim_defined_symbols = dumpdata['defined_symbols']
|
||||||
|
let b:nim_caas_enabled = g:nim_caas_enabled || index(dumpdata['defined_symbols'], 'forcecaas') != -1
|
||||||
|
|
||||||
|
for path in dumpdata['lib_paths']
|
||||||
|
if finddir(path) == path
|
||||||
|
let &l:path = path . "," . &l:path
|
||||||
|
endif
|
||||||
|
endfor
|
||||||
|
else
|
||||||
|
let b:nim_caas_enabled = 0
|
||||||
|
endif
|
||||||
|
endf
|
||||||
|
|
||||||
|
fun! s:UpdateNimLog()
|
||||||
|
setlocal buftype=nofile
|
||||||
|
setlocal bufhidden=hide
|
||||||
|
setlocal noswapfile
|
||||||
|
|
||||||
|
for entry in g:nim_log
|
||||||
|
call append(line('$'), split(entry, "\n"))
|
||||||
|
endfor
|
||||||
|
|
||||||
|
let g:nim_log = []
|
||||||
|
|
||||||
|
match Search /^nim\ .*/
|
||||||
|
endf
|
||||||
|
|
||||||
|
augroup NimVim
|
||||||
|
au!
|
||||||
|
au BufEnter log://nim call s:UpdateNimLog()
|
||||||
|
if has("python3") || has("python")
|
||||||
|
" au QuitPre * :py nimTerminateAll()
|
||||||
|
au VimLeavePre * :py nimTerminateAll()
|
||||||
|
endif
|
||||||
|
augroup END
|
||||||
|
|
||||||
|
command! NimLog :e log://nim
|
||||||
|
|
||||||
|
command! NimTerminateService
|
||||||
|
\ :exe printf("py nimTerminateService('%s')", b:nim_project_root)
|
||||||
|
|
||||||
|
command! NimRestartService
|
||||||
|
\ :exe printf("py nimRestartService('%s')", b:nim_project_root)
|
||||||
|
|
||||||
|
fun! s:CurrentNimFile()
|
||||||
|
let save_cur = getpos('.')
|
||||||
|
call cursor(0, 0, 0)
|
||||||
|
|
||||||
|
let PATTERN = "\\v^\\#\\s*included from \\zs.*\\ze"
|
||||||
|
let l = search(PATTERN, "n")
|
||||||
|
|
||||||
|
if l != 0
|
||||||
|
let f = matchstr(getline(l), PATTERN)
|
||||||
|
let l:to_check = expand('%:h') . "/" . f
|
||||||
|
else
|
||||||
|
let l:to_check = expand("%")
|
||||||
|
endif
|
||||||
|
|
||||||
|
call setpos('.', save_cur)
|
||||||
|
return l:to_check
|
||||||
|
endf
|
||||||
|
|
||||||
|
let g:nim_symbol_types = {
|
||||||
|
\ 'skParam': 'v',
|
||||||
|
\ 'skVar': 'v',
|
||||||
|
\ 'skLet': 'v',
|
||||||
|
\ 'skTemp': 'v',
|
||||||
|
\ 'skForVar': 'v',
|
||||||
|
\ 'skConst': 'v',
|
||||||
|
\ 'skResult': 'v',
|
||||||
|
\ 'skGenericParam': 't',
|
||||||
|
\ 'skType': 't',
|
||||||
|
\ 'skField': 'm',
|
||||||
|
\ 'skProc': 'f',
|
||||||
|
\ 'skMethod': 'f',
|
||||||
|
\ 'skIterator': 'f',
|
||||||
|
\ 'skConverter': 'f',
|
||||||
|
\ 'skMacro': 'f',
|
||||||
|
\ 'skTemplate': 'f',
|
||||||
|
\ 'skEnumField': 'v',
|
||||||
|
\ }
|
||||||
|
|
||||||
|
fun! NimExec(op)
|
||||||
|
let isDirty = getbufvar(bufnr('%'), "&modified")
|
||||||
|
if isDirty
|
||||||
|
let tmp = tempname() . bufname("%") . "_dirty.nim"
|
||||||
|
silent! exe ":w " . tmp
|
||||||
|
|
||||||
|
let cmd = printf("idetools %s --trackDirty:\"%s,%s,%d,%d\" \"%s\"",
|
||||||
|
\ a:op, tmp, expand('%:p'), line('.'), col('.')-1, s:CurrentNimFile())
|
||||||
|
else
|
||||||
|
let cmd = printf("idetools %s --track:\"%s,%d,%d\" \"%s\"",
|
||||||
|
\ a:op, expand('%:p'), line('.'), col('.')-1, s:CurrentNimFile())
|
||||||
|
endif
|
||||||
|
|
||||||
|
if b:nim_caas_enabled
|
||||||
|
exe printf("py nimExecCmd('%s', '%s', False)", b:nim_project_root, cmd)
|
||||||
|
let output = l:py_res
|
||||||
|
else
|
||||||
|
let output = system("nim " . cmd)
|
||||||
|
endif
|
||||||
|
|
||||||
|
call add(g:nim_log, "nim " . cmd . "\n" . output)
|
||||||
|
return output
|
||||||
|
endf
|
||||||
|
|
||||||
|
fun! NimExecAsync(op, Handler)
|
||||||
|
let result = NimExec(a:op)
|
||||||
|
call a:Handler(result)
|
||||||
|
endf
|
||||||
|
|
||||||
|
fun! NimComplete(findstart, base)
|
||||||
|
if b:nim_caas_enabled == 0
|
||||||
|
return -1
|
||||||
|
endif
|
||||||
|
|
||||||
|
if a:findstart
|
||||||
|
if synIDattr(synIDtrans(synID(line("."),col("."),1)), "name") == 'Comment'
|
||||||
|
return -1
|
||||||
|
endif
|
||||||
|
let line = getline('.')
|
||||||
|
let start = col('.') - 1
|
||||||
|
while start > 0 && line[start - 1] =~? '\w'
|
||||||
|
let start -= 1
|
||||||
|
endwhile
|
||||||
|
return start
|
||||||
|
else
|
||||||
|
let result = []
|
||||||
|
let sugOut = NimExec("--suggest")
|
||||||
|
for line in split(sugOut, '\n')
|
||||||
|
let lineData = split(line, '\t')
|
||||||
|
if len(lineData) > 0 && lineData[0] == "sug"
|
||||||
|
let word = split(lineData[2], '\.')[-1]
|
||||||
|
if a:base ==? '' || word =~# '^' . a:base
|
||||||
|
let kind = get(g:nim_symbol_types, lineData[1], '')
|
||||||
|
let c = { 'word': word, 'kind': kind, 'menu': lineData[3], 'dup': 1 }
|
||||||
|
call add(result, c)
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
endfor
|
||||||
|
return result
|
||||||
|
endif
|
||||||
|
endf
|
||||||
|
|
||||||
|
if !exists("g:neocomplcache_omni_patterns")
|
||||||
|
let g:neocomplcache_omni_patterns = {}
|
||||||
|
endif
|
||||||
|
let g:neocomplcache_omni_patterns['nim'] = '[^. *\t]\.\w*'
|
||||||
|
|
||||||
|
if !exists('g:neocomplete#sources#omni#input_patterns')
|
||||||
|
let g:neocomplete#sources#omni#input_patterns = {}
|
||||||
|
endif
|
||||||
|
let g:neocomplete#sources#omni#input_patterns['nim'] = '[^. *\t]\.\w*'
|
||||||
|
|
||||||
|
let g:nim_completion_callbacks = {}
|
||||||
|
|
||||||
|
fun! NimAsyncCmdComplete(cmd, output)
|
||||||
|
call add(g:nim_log, a:output)
|
||||||
|
echom g:nim_completion_callbacks
|
||||||
|
if has_key(g:nim_completion_callbacks, a:cmd)
|
||||||
|
let Callback = get(g:nim_completion_callbacks, a:cmd)
|
||||||
|
call Callback(a:output)
|
||||||
|
" remove(g:nim_completion_callbacks, a:cmd)
|
||||||
|
else
|
||||||
|
echom "ERROR, Unknown Command: " . a:cmd
|
||||||
|
endif
|
||||||
|
return 1
|
||||||
|
endf
|
||||||
|
|
||||||
|
fun! GotoDefinition_nim_ready(def_output)
|
||||||
|
if v:shell_error
|
||||||
|
echo "nim was unable to locate the definition. exit code: " . v:shell_error
|
||||||
|
" echoerr a:def_output
|
||||||
|
return 0
|
||||||
|
endif
|
||||||
|
|
||||||
|
let rawDef = matchstr(a:def_output, 'def\t\([^\n]*\)')
|
||||||
|
if rawDef == ""
|
||||||
|
echo "the current cursor position does not match any definitions"
|
||||||
|
return 0
|
||||||
|
endif
|
||||||
|
|
||||||
|
let defBits = split(rawDef, '\t')
|
||||||
|
let file = defBits[4]
|
||||||
|
let line = defBits[5]
|
||||||
|
exe printf("e +%d %s", line, file)
|
||||||
|
return 1
|
||||||
|
endf
|
||||||
|
|
||||||
|
fun! GotoDefinition_nim()
|
||||||
|
call NimExecAsync("--def", function("GotoDefinition_nim_ready"))
|
||||||
|
endf
|
||||||
|
|
||||||
|
fun! FindReferences_nim()
|
||||||
|
setloclist()
|
||||||
|
endf
|
||||||
|
|
||||||
|
" Syntastic syntax checking
|
||||||
|
fun! SyntaxCheckers_nim_nim_GetLocList()
|
||||||
|
let makeprg = 'nim check --hints:off --listfullpaths ' . s:CurrentNimFile()
|
||||||
|
let errorformat = &errorformat
|
||||||
|
|
||||||
|
return SyntasticMake({ 'makeprg': makeprg, 'errorformat': errorformat })
|
||||||
|
endf
|
||||||
|
|
||||||
|
function! SyntaxCheckers_nim_nim_IsAvailable()
|
||||||
|
return executable("nim")
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
if exists("g:SyntasticRegistry")
|
||||||
|
call g:SyntasticRegistry.CreateAndRegisterChecker({
|
||||||
|
\ 'filetype': 'nim',
|
||||||
|
\ 'name': 'nim'})
|
||||||
|
endif
|
||||||
|
|
||||||
|
endif
|
||||||
@@ -262,7 +262,8 @@ filetypes:
|
|||||||
---
|
---
|
||||||
name: fsharp
|
name: fsharp
|
||||||
remote: ionide/Ionide-vim
|
remote: ionide/Ionide-vim
|
||||||
dirs: :basic
|
ignored_dirs:
|
||||||
|
- ftplugin
|
||||||
filetypes:
|
filetypes:
|
||||||
- name: fsharp
|
- name: fsharp
|
||||||
linguist: F#
|
linguist: F#
|
||||||
@@ -321,7 +322,11 @@ filetypes:
|
|||||||
---
|
---
|
||||||
name: go
|
name: go
|
||||||
remote: fatih/vim-go
|
remote: fatih/vim-go
|
||||||
dirs: :go
|
ignored_dirs:
|
||||||
|
- autoload
|
||||||
|
- ftplugin
|
||||||
|
extra_dirs:
|
||||||
|
- autoload/go/config.vim
|
||||||
filetypes:
|
filetypes:
|
||||||
- name: go
|
- name: go
|
||||||
linguist: Go
|
linguist: Go
|
||||||
@@ -542,7 +547,8 @@ filetypes:
|
|||||||
---
|
---
|
||||||
name: ledger
|
name: ledger
|
||||||
remote: ledger/vim-ledger
|
remote: ledger/vim-ledger
|
||||||
dirs: :basic
|
ignored_dirs:
|
||||||
|
- ftplugin
|
||||||
filetypes:
|
filetypes:
|
||||||
- name: ledger
|
- name: ledger
|
||||||
extensions:
|
extensions:
|
||||||
@@ -655,7 +661,8 @@ filetypes:
|
|||||||
---
|
---
|
||||||
name: nim
|
name: nim
|
||||||
remote: zah/nim.vim
|
remote: zah/nim.vim
|
||||||
dirs: :basic
|
ignored_dirs:
|
||||||
|
- ftplugin
|
||||||
filetypes:
|
filetypes:
|
||||||
- name: nim
|
- name: nim
|
||||||
linguist: Nim
|
linguist: Nim
|
||||||
@@ -851,7 +858,8 @@ filetypes:
|
|||||||
---
|
---
|
||||||
name: r-lang
|
name: r-lang
|
||||||
remote: vim-scripts/R.vim
|
remote: vim-scripts/R.vim
|
||||||
dirs: :basic
|
ignored_dirs:
|
||||||
|
- ftplugin
|
||||||
filetypes:
|
filetypes:
|
||||||
- name: r
|
- name: r
|
||||||
linguist: R
|
linguist: R
|
||||||
|
|||||||
@@ -15,11 +15,8 @@ BASE_URL = 'https://raw.githubusercontent.com/github/linguist/master'
|
|||||||
DIRS = {
|
DIRS = {
|
||||||
default: %w(syntax indent compiler autoload ftplugin ctags after/syntax after/indent after/ftplugin),
|
default: %w(syntax indent compiler autoload ftplugin ctags after/syntax after/indent after/ftplugin),
|
||||||
all: %w(syntax indent compiler autoload ftplugin after extras ctags),
|
all: %w(syntax indent compiler autoload ftplugin after extras ctags),
|
||||||
basic: %w(syntax compiler indent after/syntax after/indent),
|
|
||||||
syntax: %w(syntax indent after/syntax after/indent),
|
syntax: %w(syntax indent after/syntax after/indent),
|
||||||
noafter: %w(syntax compiler indent autoload ftplugin),
|
noafter: %w(syntax compiler indent autoload ftplugin)
|
||||||
javascript: %w(syntax indent compiler autoload ftplugin ctags after/syntax after/indent after/ftplugin extras),
|
|
||||||
go: %w(autoload/go/config.vim syntax compiler indent after/syntax after/indent)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def parallel(*procs)
|
def parallel(*procs)
|
||||||
|
|||||||
Reference in New Issue
Block a user