Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[feature] Add language specific definitions extensibility example #13

Closed
kunzaatko opened this issue Mar 2, 2021 · 8 comments
Closed

Comments

@kunzaatko
Copy link
Contributor

kunzaatko commented Mar 2, 2021

Problem

Every example uses eventually uses only one lush function to define the colours.

Proposition

I think that it would be more powerful to define specific features in multiple files and require them only if necessary.

Possible solution

If I understand it correctly, what is being defined by the lush function is a table. Therefore a way to get about it would be to use vim.tbl_extend or something similar to define the colours in mutliple lush functions. If there is no reason not to do it this way, than there should be an example for this functionality, because it is very powerful and could be extensively used for more modularity and code clarity.

Example of use

I created these files for language colour definitions and would like to store them in these separate files and add them to a global colour table definition. Also the files should be added to the template folder I think for better incentive for colourscheme creation to have a greater coverage. (I have something similar for plugins...)

@kunzaatko kunzaatko changed the title Add language specific definitions extensibility example [feature] Add language specific definitions extensibility example Mar 2, 2021
@kunzaatko
Copy link
Contributor Author

Also it would make additional configuration easier. For example see gruvbox. If it were possible to have a separate lush function for a configurable feature and join them in the end, the definitions in the beginning would not be necessary.

@rktjmp
Copy link
Owner

rktjmp commented Mar 3, 2021

How do you imagine using those files you linked?

To be explicit in discussion, as they are, they define no rules for the groups, so inheriting from them would not be useful, beyond automatically clearing any hl-linking that their associated plugin does.

As I understand it, they exist as "language templates", where if you want to style haskell, you have the option of copying the haskell file to my_spec/haskell.lua, then editing it, then requiring it into your main spec.lua?

So your main spec might be

-- gruv-lush.lua
lush = require lush
haskell = require 'gruv-lush/haskell'
js = require 'gruv-lush/js'

return lush(function(){
{  
  -- somehow apply all of haskell
  -- somehow apply all of js
  Normal { ... }
})

You would likely have to have a lush-base file, which defined stuff like what symbols or keywords should look like by default, and include that into your haskell file since you likely want haskell functions to be styled the same as js functions.

(Just thinking out loud.) On the face of it, it looks like that might all behave the same as (the theoretical) #10, but actually they want different behaviour.

"Extensions" as you termed them only want a few parts of the base, where as inheritance wants to automatically apply all groups and properties, then let you override them where you want.

If base defines Comment, haskell shouldn't redefine it unless explicitly told. haskell should only "export" haskell related groups.

Right now, you can already to something like this, which is probably close to what you want:

-- base.lua
require lush
return lush(function(){
  return {
    Comment: { ... }
    Function: {...}
  }
})
-- elixir.lua
require lush
require base
return lush(function(){
  return {
    elixirCallbackDefine  { fg: base.Function.fg.ro(10), bg: base.Function.bg } -- tweak Function.
    -- this doesnt work but it would be nice if it did
    -- elixirGuard { base.Function } -- create link (might not be possible) or at least clone keys
    -- this DOES work, see #9 
    elixirGuard { base.Function, fg: base.Function.fg } -- will also pickup bg key
  }
}) 

(#9)

The sticky part is bringing it all into an actual usable theme, since you have to redefine all the groups:

-- all.lua
require lush
require base
require elixir
return lush(function(){
  return {
    elixirCallbackDefine  { fg: elixir.elixirCallbackDefine.fg ... }
   -- ... having to do this is definitely garbage.
  }
}) 

But at this point, I think you are talking about spec inheritance #10.

-- doesnt work yet
require lush, base elixir js ...

return lush.with(base, elixir, js, ...)(function(){
  -- maybe nothing even needed here
})

Sorry this comments all over the place, it's sort of a dense topic.

Do you think the first part, requiring base and setting groups off it, covers what you are talking about or not?

@kunzaatko
Copy link
Contributor Author

The first listing is most similar to the idea I had in mind. The main spec file, would include some conditions for the definition of these modules. Something like this:
./lush-theme/amazing_theme.lua:

local config = { -- user-defined in the `vimrc`
    rust = vim.g.amazing_theme_load_rust or 0,
    ...
}

local modules = {} 

-- for all the plugins and languages specified in the `vimrc`
if config.rust == 1 then
    local rust = require "lush-theme.languages.rust"
    vim.tbl_extend(modules, rust)
end

-- then the modules would be loaded in the main spec
local theme = lush(function()
   base = {
       ...
   }
   vim.g.tbl_extend(base,modules)
   return base
end)

return theme

This would allow to make some interesting things possible... For example, when I only use plugins vim-startify,undotree but the colourscheme defines 100 plugins, I could just write something like this in my vimrc:

   vim.g.amazing_theme_plugins = {
        vim_startify = true,
        undotree = true
}

And the advantage is, that I do not pay any loading time for plugins I do not use at all.

This could extend to languages and conditionally loading languages, only if they are being used...

As for the template-files I linked, I can add comments, so that the groups are not cleared and then over time, there would be comments after the groups similarly to the template of the main spec.


Another advantage of this would be, that you could have something like this in a module (plugin_module.lua):

vim.g.plugin_color_variable = tostring(hsl(90,30,50))
...
local theme = lush(function()
   ...
end)

return theme

This would enable having settings for plugins that are made by variables to be in the same file and only defined after loading.


Thank you very much for your reply and this project. It has an amazing potential.

(should I comment the groups in the templates?)

@kunzaatko
Copy link
Contributor Author

As I understand it, they exist as "language templates", where if you want to style haskell, you have the option of copying the haskell file to my_spec/haskell.lua, then editing it, then requiring it into your main spec.lua?

Yes, this could also be used for better modulation of the scheme. Now, colour schemes, that have many definitions of groups take very long to load, therefore increasing the startuptime. Would it be possible to make syntax to provide conditions similarly to something like the packer.nvim definition of packages? This could maybe compile into autocmds that are for a given filetype or similar... (You do not need groups for filetypes, that are not actually open before opening them).
The final compilation would be into something similar to this:

augroup rust 
    autocmd FileType rust hi RustComment gui=italic, guibg=red ...
    ...
augroup END

This could make the colourscheme much smaller and faster to load with the same amount of definitions... right?

@kunzaatko
Copy link
Contributor Author

Sorry for being a little bit spamy, but I thought of a better way...
The files from the filetype templates should create files in the syntax folder of the colourscheme. These files would alter the filetype specific groups of the colourscheme and would be compiled in the same way that the main spec is compiled. I would be eager to implement this. Should I make a fork or would you mind giving me write permission so that I can branch this repo and you could maybe check it incrementally as I go (I think that this will take me a week or two because I currently do not have much time...)? @rktjmp Do you have an idea of a similar approach with the plugin specific configuration, or does it have to be some kind of conditions there?

@rktjmp
Copy link
Owner

rktjmp commented Mar 6, 2021

See post on #8, I think the extends system will do most of what you want right? Though this issue feels like it's maybe being pulled in a few directions (conditional extends, syntax template files and performance of large themes).

@kunzaatko
Copy link
Contributor Author

kunzaatko commented Mar 6, 2021

Yeah. I think that it helps a lot! Maybe we could split this into different issues?

  1. conditions and conditional loading (best solved by Combining | Merging | Extending themes #8)
  2. language syntax files generation through lush
  3. large themes and plugin incorporation (including templates? I have them locally, but the ability to conditionally merge them into the theme would have to be solved)

The last two would help with the performance IMO. Also we might have an issue about the templates (language and plugin)... I have some kind of templates as I shared through the gist for languages and have some for plugins locally. We only need to agree on the implementation.

@rktjmp
Copy link
Owner

rktjmp commented Mar 7, 2021

Closing in favour of #10 #18 #19 #17

@rktjmp rktjmp closed this as completed Mar 7, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants