itchyny / lightline.vim

A light and configurable statusline/tabline plugin for Vim
MIT License
6.73k stars 312 forks source link

Calling lua function from `g:lightline` config #657

Closed dccboss closed 1 year ago

dccboss commented 1 year ago

My current vim.g.lightline in init.lua:

  { "itchyny/lightline.vim",
    config = function()
      vim.g.lightline = {
        -- powerlineish, rosepine, nord, ayu_light, seoul256, Tomorrow, materia, ayu_dark, Tomorrow_Night_Bright, PaperColor_light,
        -- default, powerline, 16color, Tomorrow_Night, selenized_white, molokai, Tomorrow_Night_Blue, selenized_light, Tomorrow_Night_Eighties,
        -- PaperColor, selenized_black, wombat, one, PaperColor_dark, apprentice, deus, ayu_mirage, darcula, landscape, OldHope, jellybeans,
        -- material, solarized, srcery_drk, selenized_dark, simpleblack, dragoon
        colorscheme = "dragoon",
        active = {
          left = {
            { "mode", "paste" },
            { "readonly", "filename", "modified" },
            { "gitbranch", "gitstatus", "cocstatus" },
          },
          right = {
            { "lineinfo" },
            { "percent" },
            { "filetype" },
          },
        },
        component_function = {
          gitbranch = 'gitBranch',
          gitstatus = 'GitStatus',
          cocstatus = 'coc#status',
        },
        component_expand = {
          filetype = "lightline#filetype",
        },
      }
    end,
  },

and the lua function gitBranch:

--[[ function to add  to branch display --]]
function _G.gitBranch()
  return " " .. vim.fn["gitbranch#name"]()
end

I've tried:

gitbranch = 'lua gitBranch'

I have defined function AS a vim function, as a temporary solution:

--[[ Current kludge for gitBranch() --]] ]
vim.api.nvim_exec(
[[
function! g:VimGitBranch()
  return " " .. gitbranch#name()
endfunction
]],
true)

Using it as:

gitbranch = 'VimGitBranch',

This works for now, but it'd be nice to be able to call the native lua function directly.

itchyny commented 1 year ago

I created lightline plugin before NeoVim was forked from Vim, and Lua API became so common. So the design does not look well with the Lua API (I don't use NeoVim and not tested the plugin with the Lua API). Having said that, gitbranch = 'v:lua.gitBranch' should work, but it needs some patch fixing code not working with v:lua. I can't include as it is, the question here is how can we check the function existence of v:lua.F?

diff --git a/autoload/lightline.vim b/autoload/lightline.vim
index e1f09ca..5ca6c20 100644
--- a/autoload/lightline.vim
+++ b/autoload/lightline.vim
@@ -296,7 +296,7 @@ endfunction
 function! s:subseparator(components, subseparator, expanded) abort
   let [a, c, f, v, u] = [a:components, s:lightline.component, s:lightline.component_function, s:lightline.component_visible_condition, s:lightline.component_function_visible_condition]
   let xs = map(range(len(a:components)), 'a:expanded[v:val] ? "1" :
-        \ has_key(f, a[v:val]) ? (has_key(u, a[v:val]) ? "(".u[a[v:val]].")" : (exists("*".f[a[v:val]]) ? "" : "exists(\"*".f[a[v:val]]."\")&&").f[a[v:val]]."()!=#\"\"") :
+        \ has_key(f, a[v:val]) ? (has_key(u, a[v:val]) ? "(".u[a[v:val]].")" : f[a[v:val]]."()!=#\"\"") :
         \ has_key(v, a[v:val]) ? "(".v[a[v:val]].")" : has_key(c, a[v:val]) ? "1" : "0"')
   return '%{' . (xs[0] ==# '1' || xs[0] ==# '(1)' ? '' : xs[0] . '&&(') . join(xs[1:], '||') . (xs[0] ==# '1' || xs[0] ==# '(1)' ? '' : ')') . '?"' . a:subseparator . '":""}'
 endfunction
@@ -380,7 +380,7 @@ function! s:expand(components) abort
 endfunction

 function! s:func(name) abort
-  return exists('*' . a:name) ? '%{' . a:name . '()}' : '%{exists("*' . a:name . '")?' . a:name . '():""}'
+  return '%{' . a:name . '()}'
 endfunction

 function! s:line(tabline, inactive) abort
pauldesmondparker commented 1 year ago

Thank you, worked like a charm. Not sustainable, but at least it was nice to see it work directly.

Any chance of using this, to check for the Lua function:

function! IsLuaFunction(name) abort
    return luaeval(a:name)->type() == v:t_func
endfunction
itchyny commented 1 year ago

I don't like to use luaeval here. I believe we could check function existence in a consistent way, hope anyone asks NeoVim devs if they have thoughts on making exists("*v:lua.F") works.

itchyny commented 1 year ago

Although this issue isn't resolved, I can do nothing to fix in this plugin so closing the issue. I still think the request for NeoVim https://github.com/neovim/neovim/issues/24587#issuecomment-1667793260 is reasonable. Please help them by writing a NeoVim patch to make Vim script plugins work well on NeoVim.

jonhoo commented 8 months ago

@itchyny https://github.com/neovim/neovim/pull/26485 has landed and makes exists able to check for v:lua functions :tada: I'm hoping that means there's a path to getting v:lua.F to work? Currently it yields:

E15: Invalid expression: v:lua
itchyny commented 8 months ago

@jonhoo @pauldesmondparker @glepnir NeoVim v0.9.5 does not work with exists("*v:lua.F"). Existence check for user-defined functions should be prefixed by *.

glepnir commented 8 months ago

hmm i dont know why it through invaid expression. i don't check lightline code :P should return 0 when it start with *v:lua ..for viml user custom function it start with * for lua i just use v:lua directly...let me think about it.

itchyny commented 8 months ago

This check should check "*v:lua." right? The patch implements in the different way than proposed by the original issue.

glepnir commented 8 months ago

Yes. Opportunistic but breaks compatibility T.T working on it