What is the idiomatic way to share functions between files? - vim

I have a plugin function called InComment() stored in magic.vim *1
I would like to share it between two ftplugin files:
ftplugin/c.vim
ftplugin/python.vim
What is the idiomatic way to call InComment() function from my ftplugin files?
*1 plugin/magic.vim
function! s:InComment() " {{{
let syn = s:SyntaxName(line('.'), col('.') - 1, 1)
if syn =~? 'comment'
return 1
else
return 0
endif
endfunction "}}}

The document referenced by Prince Goulash has everything you need. To answer you specifically, you need to give the function a name based on the name of your plugin, like this:
function! magic#InComment() " {{{
let syn = s:SyntaxName(line('.'), col('.') - 1, 1)
if syn =~? 'comment'
return 1
else
return 0
endif
endfunction "}}}
Then you can call it from your plugin like this:
call magic#InComment()
The part before the # has to match the name of your plugin file. This will also cause the plugin to be autoloaded when the function is called.

I have just found this question while trying to answer it myself.
There is a Vim help section on Writing Library Scripts, which looks like exactly what we need!
(Note: I haven't actually tried it yet. I will update this post if I run into problems.)

Related

In nixos, how to get vim syntax highlighting for the nix language?

I'm trying to add vim syntax highlighting for the nix language, and have been trying to use this github repo to do that.
Within that repo I've located the nix.vim file. I've tried placing that in ~/.vim per the repository's 'manual installation' instructions, but this did not work to make the colors appear.
Since that attempt, I've been trying to get the syntax coloring by altering my /etc/nixos/configuration.nix file, and in that vein have been trying to make sense out of this documentation. Thus I've added to my configuration file this programs.vim code block,
programs.vim = {
enable = true;
extraConfig = ''
'';
};
and pasted the contents of the entire nix.vim file into the string of that programs.vim.extraConfig section. Thus block added to my configuration.nix is:
programs.vim = {
enable = true;
extraConfig = ''
" Vim syntax file
" Language: Nix
" Maintainer: Daiderd Jordan <daiderd#gmail.com>
" URL: https://github.com/LnL7/vim-nix
if exists("b:current_syntax")
finish
endif
syn keyword nixBoolean true false
syn keyword nixNull null
syn keyword nixRecKeyword rec
syn keyword nixOperator or
syn match nixOperator '!=\|!'
syn match nixOperator '<=\?'
syn match nixOperator '>=\?'
syn match nixOperator '&&'
syn match nixOperator '//\='
syn match nixOperator '=='
syn match nixOperator '?'
syn match nixOperator '||'
syn match nixOperator '++\='
syn match nixOperator '-'
syn match nixOperator '\*'
syn match nixOperator '->'
syn match nixParen '[()]'
syn match nixInteger '\d\+'
syn keyword nixTodo FIXME NOTE TODO OPTIMIZE XXX HACK contained
syn match nixComment '#.*' contains=nixTodo,#Spell
syn region nixComment start=+/\*+ end=+\*/+ contains=nixTodo,#Spell
syn region nixInterpolation matchgroup=nixInterpolationDelimiter start="\${" end="}" contained contains=#nixExpr,nixInterpolationParam
syn match nixSimpleStringSpecial /\\\%([nrt"\\$]\|$\)/ contained
syn match nixStringSpecial /''['$]/ contained
syn match nixStringSpecial /\$\$/ contained
syn match nixStringSpecial /''\\[nrt]/ contained
syn match nixInvalidSimpleStringEscape /\\[^nrt"\\$]/ contained
syn match nixInvalidStringEscape /''\\[^nrt]/ contained
syn region nixSimpleString matchgroup=nixStringDelimiter start=+"+ skip=+\\"+ end=+"+ contains=nixInterpolation,nixSimpleStringSpecial,nixInvalidSimpleStringEscape
syn region nixString matchgroup=nixStringDelimiter start=+''+ skip=+''['$\\]+ end=+''+ contains=nixInterpolation,nixStringSpecial,nixInvalidStringEscape
syn match nixFunctionCall "[a-zA-Z_][a-zA-Z0-9_'-]*"
syn match nixPath "[a-zA-Z0-9._+-]*\%(/[a-zA-Z0-9._+-]\+\)\+"
syn match nixHomePath "\~\%(/[a-zA-Z0-9._+-]\+\)\+"
syn match nixSearchPath "[a-zA-Z0-9._+-]\+\%(\/[a-zA-Z0-9._+-]\+\)*" contained
syn match nixPathDelimiter "[<>]" contained
syn match nixSearchPathRef "<[a-zA-Z0-9._+-]\+\%(\/[a-zA-Z0-9._+-]\+\)*>" contains=nixSearchPath,nixPathDelimiter
syn match nixURI "[a-zA-Z][a-zA-Z0-9.+-]*:[a-zA-Z0-9%/?:#&=$,_.!~*'+-]\+"
syn match nixAttributeDot "\." contained
syn match nixAttribute "[a-zA-Z_][a-zA-Z0-9_'-]*\ze\%([^a-zA-Z0-9_'.-]\|$\)" contained
syn region nixAttributeAssignment start="=" end="\ze;" contained contains=#nixExpr
syn region nixAttributeDefinition start=/\ze[a-zA-Z_"$]/ end=";" contained contains=nixComment,nixAttribute,nixInterpolation,nixSimpleString,nixAttributeDot,nixAttributeAssignment
syn region nixInheritAttributeScope start="(" end=")" contained contains=nixComment,nixAttributeDot
syn region nixAttributeDefinition matchgroup=nixInherit start="\<inherit\>" end=";" contained contains=nixComment,nixInheritAttributeScope,nixAttribute
syn region nixAttributeSet start="{" end="}" contains=nixComment,nixAttributeDefinition
" vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
syn region nixArgumentDefinitionWithDefault matchgroup=nixArgumentDefinition start="[a-zA-Z_][a-zA-Z0-9_'-]*\ze\%(\s\|#.\{-\}\n\|\n\|/\*\_.\{-\}\*/\)*?\#=" matchgroup=NONE end="[,}]\#=" transparent contained contains=#nixExpr
" vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
syn match nixArgumentDefinition "[a-zA-Z_][a-zA-Z0-9_'-]*\ze\%(\s\|#.\{-\}\n\|\n\|/\*\_.\{-\}\*/\)*[,}]\#=" contained
syn match nixArgumentEllipsis "\.\.\." contained
syn match nixArgumentSeparator "," contained
" vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
syn match nixArgOperator '#\%(\s\|#.\{-\}\n\|\n\|/\*\_.\{-\}\*/\)*[a-zA-Z_][a-zA-Z0-9_'-]*\%(\s\|#.\{-\}\n\|\n\|/\*\_.\{-\}\*/\)*:'he=s+1 contained contains=nixAttribute
" vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
syn match nixArgOperator '[a-zA-Z_][a-zA-Z0-9_'-]*\%(\s\|#.\{-\}\n\|\n\|/\*\_.\{-\}\*/\)*#'hs=e-1 contains=nixAttribute nextgroup=nixFunctionArgument
" This is a bit more complicated, because function arguments can be passed in a
" very similar form on how attribute sets are defined and two regions with the
" same start patterns will shadow each other. Instead of a region we could use a
" match on {\_.\{-\}}, which unfortunately doesn't take nesting into account.
"
" So what we do instead is that we look forward until we are sure that it's a
" function argument. Unfortunately, we need to catch comments and both vertical
" and horizontal white space, which the following regex should hopefully do:
"
" "\%(\s\|#.\{-\}\n\|\n\|/\*\_.\{-\}\*/\)*"
"
" It is also used throught the whole file and is marked with 'v's as well.
"
" Fortunately the matching rules for function arguments are much simpler than
" for real attribute sets, because we can stop when we hit the first ellipsis or
" default value operator, but we also need to paste the "whitespace & comments
" eating" regex all over the place (marked with 'v's):
"
" Region match 1: { foo ? ... } or { foo, ... } or { ... } (ellipsis)
" vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv {----- identifier -----}vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
syn region nixFunctionArgument start="{\ze\%(\s\|#.\{-\}\n\|\n\|/\*\_.\{-\}\*/\)*\%([a-zA-Z_][a-zA-Z0-9_'-]*\%(\s\|#.\{-\}\n\|\n\|/\*\_.\{-\}\*/\)*[,?}]\|\.\.\.\)" end="}" contains=nixComment,nixArgumentDefinitionWithDefault,nixArgumentDefinition,nixArgumentEllipsis,nixArgumentSeparator nextgroup=nixArgOperator
" Now it gets more tricky, because we need to look forward for the colon, but
" there could be something like "{}#foo:", even though it's highly unlikely.
"
" Region match 2: {}
" vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv#vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv{----- identifier -----} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
syn region nixFunctionArgument start="{\ze\%(\s\|#.\{-\}\n\|\n\|/\*\_.\{-\}\*/\)*}\%(\%(\s\|#.\{-\}\n\|\n\|/\*\_.\{-\}\*/\)*#\%(\s\|#.\{-\}\n\|\n\|/\*\_.\{-\}\*/\)*[a-zA-Z_][a-zA-Z0-9_'-]*\)\%(\s\|#.\{-\}\n\|\n\|/\*\_.\{-\}\*/\)*:" end="}" contains=nixComment nextgroup=nixArgOperator
" vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
syn match nixSimpleFunctionArgument "[a-zA-Z_][a-zA-Z0-9_'-]*\ze\%(\s\|#.\{-\}\n\|\n\|/\*\_.\{-\}\*/\)*:/\#!"
syn region nixList matchgroup=nixListBracket start="\[" end="\]" contains=#nixExpr
syn region nixLetExpr matchgroup=nixLetExprKeyword start="\<let\>" end="\<in\>" contains=nixComment,nixAttributeDefinition
syn keyword nixIfExprKeyword then contained
syn region nixIfExpr matchgroup=nixIfExprKeyword start="\<if\>" end="\<else\>" contains=#nixExpr,nixIfExprKeyword
syn region nixWithExpr matchgroup=nixWithExprKeyword start="\<with\>" matchgroup=NONE end=";" contains=#nixExpr
syn region nixAssertExpr matchgroup=nixAssertKeyword start="\<assert\>" matchgroup=NONE end=";" contains=#nixExpr
syn cluster nixExpr contains=nixBoolean,nixNull,nixOperator,nixParen,nixInteger,nixRecKeyword,nixConditional,nixBuiltin,nixSimpleBuiltin,nixComment,nixFunctionCall,nixFunctionArgument,nixSimpleFunctionArgument,nixPath,nixHomePath,nixSearchPathRef,nixURI,nixAttributeSet,nixList,nixSimpleString,nixString,nixLetExpr,nixIfExpr,nixWithExpr,nixAssertExpr,nixInterpolation
" These definitions override #nixExpr and have to come afterwards:
syn match nixInterpolationParam "[a-zA-Z_][a-zA-Z0-9_'-]*\%(\.[a-zA-Z_][a-zA-Z0-9_'-]*\)*" contained
" Non-namespaced Nix builtins as of version 2.0:
syn keyword nixSimpleBuiltin
\ abort baseNameOf derivation derivationStrict dirOf fetchGit
\ fetchMercurial fetchTarball import isNull map placeholder removeAttrs
\ scopedImport throw toString
" Namespaced and non-namespaced Nix builtins as of version 2.0:
syn keyword nixNamespacedBuiltin contained
\ abort add addErrorContext all any attrNames attrValues baseNameOf
\ catAttrs compareVersions concatLists concatStringsSep currentSystem
\ currentTime deepSeq derivation derivationStrict dirOf div elem elemAt
\ fetchGit fetchMercurial fetchTarball fetchurl filter \ filterSource
\ findFile foldl' fromJSON functionArgs genList \ genericClosure getAttr
\ getEnv hasAttr hasContext hashString head import intersectAttrs isAttrs
\ isBool isFloat isFunction isInt isList isNull isString langVersion
\ length lessThan listToAttrs map match mul nixPath nixVersion
\ parseDrvName partition path pathExists placeholder readDir readFile
\ removeAttrs replaceStrings scopedImport seq sort split splitVersion
\ storeDir storePath stringLength sub substring tail throw toFile toJSON
\ toPath toString toXML trace tryEval typeOf unsafeDiscardOutputDependency
\ unsafeDiscardStringContext unsafeGetAttrPos valueSize
syn match nixBuiltin "builtins\.[a-zA-Z']\+"he=s+9 contains=nixComment,nixNamespacedBuiltin
hi def link nixArgOperator Operator
hi def link nixArgumentDefinition Identifier
hi def link nixArgumentEllipsis Operator
hi def link nixAssertKeyword Keyword
hi def link nixAttribute Identifier
hi def link nixAttributeDot Operator
hi def link nixBoolean Boolean
hi def link nixBuiltin Special
hi def link nixComment Comment
hi def link nixConditional Conditional
hi def link nixHomePath Include
hi def link nixIfExprKeyword Keyword
hi def link nixInherit Keyword
hi def link nixInteger Integer
hi def link nixInterpolation Macro
hi def link nixInterpolationDelimiter Delimiter
hi def link nixInterpolationParam Macro
hi def link nixInvalidSimpleStringEscape Error
hi def link nixInvalidStringEscape Error
hi def link nixLetExprKeyword Keyword
hi def link nixNamespacedBuiltin Special
hi def link nixNull Constant
hi def link nixOperator Operator
hi def link nixPath Include
hi def link nixPathDelimiter Delimiter
hi def link nixRecKeyword Keyword
hi def link nixSearchPath Include
hi def link nixSimpleBuiltin Keyword
hi def link nixSimpleFunctionArgument Identifier
hi def link nixSimpleString String
hi def link nixSimpleStringSpecial SpecialChar
hi def link nixString String
hi def link nixStringDelimiter Delimiter
hi def link nixStringSpecial Special
hi def link nixTodo Todo
hi def link nixURI Include
hi def link nixWithExprKeyword Keyword
" This could lead up to slow syntax highlighting for large files, but usually
" large files such as all-packages.nix are one large attribute set, so if we'd
" use sync patterns we'd have to go back to the start of the file anyway
syn sync fromstart
let b:current_syntax = "nix"
'';
};
This gives me problems on the line syn match nixStringSpecial /''['$]/ contained because of the double-quotes '' prematurely ending the nix string.
At this point I'm not sure whether I should try to sort out the string delimiting issues here, or try something else. Is this on the right track towards getting vim highlighting for the nix language working on my nixos machine?
TL;DR
Put the plugin files in the proper runtimepath directories.
One solution with packages is
# git clone https://github.com/LnL7/vim-nix ~/.vim/pack/nix-stuff/start/vim-nix
Adjust accordingly if you version .vim with git and want to use submodules.
Summarising Plugin layout in the dark ages and :h runtimepath, vim looks for plugin scripts in the following places on the runtimepath:
filetype.vim filetypes by file name |new-filetype|
scripts.vim filetypes by file contents |new-filetype-scripts|
autoload/ automatically loaded scripts |autoload-functions|
colors/ color scheme files |:colorscheme|
compiler/ compiler files |:compiler|
doc/ documentation |write-local-help|
ftplugin/ filetype plugins |write-filetype-plugin|
indent/ indent scripts |indent-expression|
keymap/ key mapping files |mbyte-keymap|
lang/ menu translations |:menutrans|
menu.vim GUI menus |menu.vim|
pack/ packages |:packadd|
plugin/ plugin scripts |write-plugin|
print/ files for printing |postscript-print-encoding|
spell/ spell checking files |spell|
syntax/ syntax files |mysyntaxfile|
tutor/ files for vimtutor |tutor|
Notice how certain locations have semantic meaning: syntax versus filetype versus generic "load all the time" plugins.
Now, getting all the plugin files to the right spots is tricky:
In the past, when you wanted to use a plugin someone else wrote you would download the files and place them, one-by-one, into the appropriate directories. You could also use zip or tar to do the placing for you.
There are a few significant problems with this approach:
What happens when you want to update a plugin? You can overwrite the old files, but how do you know if the author deleted a file that you now need to delete by hand?
What if two plugins happen to have a file with the same name (like utils.vim or something generic like that)? Sometimes you can simply rename it, but if it's in autoload/ or another directory where the names matter you've got to edit the plugin yourself. Not fun.
People came up with several hacks to try to make things easier, like Vimballs. Luckily we don't need to suffer through these ugly hacks any more. (A New Hope, Steve Losh)
The result is that most vim plugins on github are structured after 'runtimepath' entries. They have syntax, ftplugin, or compiler directories as needed.
Pre vim-8, the standard solution was one of the many plugin managers (give it a Google; there are a lot). My favorite was pathogen from Tim Pope, because it worked so elegantly with submodules.
Since vim-8, I've moved to using packages, which you can read about at :h packages.
As already mentioned in the comment above the solution to get it working is the following:
The nix.vim syntax file needs to be placed inside the ~/.vim/syntax directory and the following line needs to be added to your .vimrc:
au BufRead,BufNewFile *.nix set filetype=nix
This line ensures that vim recognizes the filetype of .nix files and activates the correct syntax highlighting.

Vim - Overwrite Plugin Scoped Function

I've a plugin in Vim and I don't like the behavior of a single function within it. But it isn't rly a case to open a pull request, but more an extension for it.
I know that overwriting a function ist possible by using a bang as postfix, as soon as the new definition comes after the previous one. But how can I do such thing, if this method is scoped to a script within a plugin?
I wasn't able to find a hint in _Vim_s help, nor by request a search engine. Anybody aware of this topic, at least if he can say that it is simply not possible.
A short example:
plugin/autoload/plugin.vim
...
function! s:foo() {
// behavior I would like to adjust
}
...
~/.vimrc
function! foo() {
// the "correct" behavior
}
Thanks for any help!
Actually it is possible. But as #romainl said, you'd better suggest your patch to the plugin maintainer or ask for a variation point.
Regarding the how.
First, you'll need to identify the script number of this autoload plugin. Let's say that :scriptname says it's 210. In order to do that automatically I have a lh#askvim#scriptid() function in my library plugin that does the job -- see the current definition at the end of the answer.
Then, to override the s:foo() function, you'll need to provide a new definition for
function! <SNR>210_Foo()
new definition
endfunction
(I've just tested it with vim 8.0-1157)
IOW, we can override a script-local function. However, I haven't found how to override a script-local variable directly without a reference to its s: dictionary. We could inject setter/getter functions to a specific variable or a function that returns the local s: dictionary.
lh#askvim#scriptid() current definition is the following
" Function: lh#askvim#execute(command) {{{3
" #since Version 4.0.0
if exists('*execute')
function! lh#askvim#execute(command) abort
return split(execute(a:command), "\n")
endfunction
else
function! lh#askvim#execute(command) abort
return s:beware_running_through_client_server ? [] : split(lh#askvim#exe(a:command), "\n")
endfunction
endif
" Function: lh#askvim#scriptnames() {{{3
function! lh#askvim#scriptnames() abort
let scripts = lh#askvim#execute('scriptnames')
let s:scripts = map(copy(scripts), 'split(v:val, "\\v:=\\s+")')
call lh#list#map_on(s:scripts, 1, 'fnamemodify(v:val, ":p")')
return s:scripts
endfunction
" Function: lh#askvim#scriptid(name) {{{3
function! lh#askvim#scriptid(name, ...) abort
let last_change = get(a:, 1, 0)
if last_change || !exists('s:scripts')
call lh#askvim#scriptnames()
endif
let matches = filter(copy(s:scripts), 'v:val[1] =~ a:name')
if len(matches) > 1
throw "Too many scripts match `".a:name."`: ".string(matches)
elseif empty(matches)
if last_change
throw "No script match `".a:name."`"
else
return lh#askvim#scriptid(a:name, 1)
endif
endif
return matches[0][0]
endfunction
That is not possible.
s:foo() is scoped to the script it belongs to (see :help s:) so it can't be accessed from anywhere else.
Fork it.
Make the desired changes to your fork.
Use your fork instead of the original.
Consider submitting a pull request.

Best way to create substitution macros in vim

I'd like to set up some custom auto-complete macros in vim. I'm thinking something like this (| represents the cursor position):
it<TAB>|
immediately becomes:
it("|", function () {
});
Is this possible using straight vim, or would I need a plugin? If so, is there a preferred plugin out there?
Using an abbreviation you could write something like this:
inorea it it("", function () {<cr>});<c-o>k<c-o>f"
The purpose of <c-o>k<c-o>f" at the end is to reposition your cursor inside the double quotes, but it may not work all the time.
Using a mapping, you could try this:
ino <expr> <tab> <sid>expand_last_word()
let s:your_expansions = {
\ 'it': '\<c-w>it(\"\", function () {\<cr>});\<c-o>k\<right>',
\ }
fu! s:expand_last_word() abort
let last_word = matchstr(getline('.'), '\v<\k+%'.col('.').'c')
return has_key(s:your_expansions, last_word)
\ ? eval('"'.s:your_expansions[last_word].'"')
\ : "\<tab>"
endfu
You would have to add your abbreviations and their expansions inside the dictionary s:your_expansions.
Using the :read command, you could define larger snippets of code, and split them across several files:
ino <expr> <tab> <sid>expand_last_word()
fu! s:expand_last_word() abort
let last_word = matchstr(getline('.'), '\v<\k+%'.col('.').'c')
if last_word ==# 'it'
return "\<c-w>\<c-o>:r /path/to/some_file\<cr>\<c-o>f\"\<right>"
endif
return "\<tab>"
endfu
Here /path/to/some_file should contain your snippet:
it("", function () {
});
They are very simple solutions, if you want something more robust, you probably need a snippets plugin. One of them is UltiSnips, which requires that your Vim version has been compiled with Python support (:echo has('python') or :echo has('python3') returns 1).
With UltiSnips, you would write your snippet like this:
snippet it "your description" b
it("$0", function () {
});
endsnippet
Here the definition is included between the keywords snippet and endsnippet. On the 1st line, you can describe the purpose of your snippet, inside the string in double quotes. It will be displayed by UltiSnips inside a list, if you've defined several snippets with the same tab trigger, and there's an ambiguity.
The ending b is an option to prevent the tab trigger it from being expanded anywhere else than the beginning of a line.
$0 is a tabstop, it stands for the position in which you want the cursor to be, once the snippet has been fully expanded.
The readme page on github gives a quick start, and some links to videos.
If you want to have a look at the snippets written by other people, you can install vim-snippets.
There are other snippet managers but I don't know them well enough to describe the syntax of their snippets. If you want a comparison, here's one, and here are links for some of them:
snipmate
mu-template
neosnippet
xptemplate
Here is a abbreviation that you can use for your particular example
:inoreabbrev it it("", function () {<cr>});<esc>kf"a
Typing it followed by ctrl + ] in insert mode will render
it("|", function () {
});
and keep you in insert mode.
But I would definitely go for ultisnips and there is a screencast for creating snippets on the same page. That's why I am omitting the snippet here as you can do it yourself.

abstract and reuse parts of a map command in vimrc

I wrote a map command in vim that verges on the line of being too complicated for my taste. I'd like to:
Abstract away parts, or at least spit them into multiple lines and explain each.
Reuse most of it with only 2 things, changing only 2 things in it each time.
The command uses the vim-pandoc plugin to create an Html file out of the current pandoc file and copy it to clipboard.
nnoremap <leader><leader>11 :w<cr>:Pandoc html<cr>:sleep 100m<cr>:e <c-r>=expand('%:r')<cr>.html<cr>ggVG"+y:b#<cr>:bd #<cr>
My first attempt is thus:
nnoremap <expr> <leader><leader>22 MyFunc()
func! MyFunc()
let save = ':w<cr>'
let runPandoc = ':Pandoc html<cr>'
let sleep = ':sleep 100m<cr>'
let viewResult = ':e ' . expand('%:r') . '.html' . '<cr>'
let copyAll = 'ggVG"+y'
let backToPrevBuf = ':b#<cr>'
return save . runPandoc . sleep . viewResult . copyAll . backToPrevBuf
endfunc
However, this does not work because it has <cr> in the returned value instead of actually executing enter.
Using this I can pass an arg to MyFunc that will change the html portions to other filetypes.
My two questions are:
Is there a better, more direct way of abstracting away portions of long maps?
How can I solve the issue with the <cr> appearing in the result instead of actually meaning "Press the enter button".
Thanks for the help!
EDIT:
After getting suggestions I now have the current version, it seems a bit verbose.
While I can wrap the feedkeys to be a shorter name with the 'n' parameter, is there anything else I can do?
func! MyFunc()
call feedkeys(":w\<cr>",'n')
call feedkeys(":Pandoc html\<cr>",'n')
call feedkeys(":sleep 100m\<cr>",'n')
call feedkeys(':e ' . expand('%:r') . '.html' . "\<cr>",'n')
"TODO read about :%y+ understand why it copies the entire file
call feedkeys('ggVG"+y','n')
call feedkeys(":b#\<cr>",'n')
endfunc
EDIT:
Finally, I've understood what it means to get rid of the feedkeys, and now I reached the final destination:
nnoremap <silent> <leader><leader>22 :call MyFunc()<cr><cr>
func! MyFunc()
w
Pandoc html
sleep 100m
execute 'e' (expand('%:r') . '.html')
%y+
b#
endfunc
Thanks for the help!
Is there a better, more direct way of abstracting away portions of
long maps?
Since you have already called a function, and the function just concatenate the rhs mappings, why not just do the actual work in your function, and just map to execute the function like :nnoremap whatever :call yourFunc()<cr>
How can I solve the issue with the <cr> appearing in the result
instead of actually meaning "Press the enter button".
Use "\<cr>"

Vim statusline does not expand color/highlight group from expression

I wrote a function which returns a string:
function! StatusBricks()
let l:stat = Brick(statusbricks#ReportLinecount('raw'), {
\ 'brick_color': 'LineNr',
\ 'delimiter_position': 'right',
\ 'delimiter_right': '❯'
\ })
return l:stat
endfunction
The result has the following format, generated by Brick():
%#HighlightGroup#SomeData
When I use the function as an expression inside the statusline I expect the highlight group to get expanded in order to colorize the appropriate statusline section:
set statusline =%{StatusBricks()}
But what I get is a statusline literally showing %#HighlightGroup#ExpandedData rather than ExpandedData:
What am I doing wrong?
The result of %{ isn't interpreted further, however the result of %! is. Use
set statusline=%!StatusBricks()
%! doesn't appear to have a tag in the helpfile, but it's mentioned near the beginning of :help 'statusline'.
Following your comment: if you want different colours in the statusline depending on the state of each particular window, then you can highlight an empty string if you don't want a particular highlight to appear. E.g.
set stl=%#error#%r%#search#
Only read-only windows (e.g. open a help buffer) will have the read-only flag displayed in red. Admittedly this can get complicated depending on your highlighting requirements.
tl;dr - use {% %}
I realise this is an old question, but I found an answer that future readers might use.
Rather than
set statusline =%{StatusBricks()}
you need
set statusline =%{%StatusBricks()%}
From :help 'statusline':
{% - This is almost same as { except the result of the expression is
re-evaluated as a statusline format string. Thus if the
return value of expr contains % items they will get expanded.
The expression can contain the } character, the end of
expression is denoted by %}.
The For example:
func! Stl_filename() abort
return "%t"
endfunc
`stl=%{Stl_filename()}` results in `"%t"`
`stl=%{%Stl_filename()%}` results in `"Name of current file"`

Resources