Skip to content
This repository has been archived by the owner on Sep 20, 2023. It is now read-only.

Commit

Permalink
feat!: add color theme support
Browse files Browse the repository at this point in the history
Allow adding color themes to Feline and switching between them on the
fly.

BREAKING CHANGE: The `colors` configuration option in the setup function
now needs to be renamed to `theme`.
  • Loading branch information
famiu authored and lukas-reineke committed Dec 22, 2021
1 parent 29b11b5 commit 47dc59e
Show file tree
Hide file tree
Showing 6 changed files with 205 additions and 63 deletions.
72 changes: 60 additions & 12 deletions USAGE.md
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,7 @@ If a string, it'll use the given string as the name of the component highlight g

If it's a table, it'll automatically generate a highlight group for you based on the given values. The hl table can have four values: `fg`, `bg`, `style` and `name`.

The `fg` and `bg` values are strings that represent the RGB hex or [name](#value-presets) of the foreground and background color of the highlight, respectively. (eg: `'#FFFFFF'`, `'white'`). If `fg` or `bg` is not provided, it uses the default foreground or background color provided in the `setup()` function, respectively.
The `fg` and `bg` values are strings that represent the RGB hex or [name](#themes) of the foreground and background color of the highlight, respectively. (eg: `'#FFFFFF'`, `'white'`). If `fg` or `bg` is not provided, it uses the default foreground or background color provided in the `setup()` function, respectively.

The `style` value is a string that determines the formatting style of the component's text (do `:help attr-list` in Neovim for more info). By default it is set to `'NONE'`

Expand Down Expand Up @@ -327,7 +327,7 @@ end

There are two types of separator values that you can put in a component, which are `left_sep` and `right_sep`, which represent the separator on the left and the right side of the component, respectively.

The value of `left_sep` and `right_sep` can just be set to a string that's displayed. You can use a function that returns a string just like the other component values. The value can also be equal to the name of one of the [separator presets](#value-presets).
The value of `left_sep` and `right_sep` can just be set to a string that's displayed. You can use a function that returns a string just like the other component values. The value can also be equal to the name of one of the [separator presets](#separator-presets).

The value of `left_sep` and `right_sep` can also be a table or a function returning a table. Inside the table there can be three values, `str`, `hl` and `always_visible`. `str` represents the separator string and `hl` represents the separator highlight. The separator's highlight works just like the component's `hl` value. The only difference is that the separator's `hl` by default uses the parent's background color as its foreground color.

Expand Down Expand Up @@ -474,8 +474,8 @@ custom_providers = {
}
```

- `colors` - A table containing custom [color value presets](#value-presets). The value of `colors.fg` and `colors.bg` also represent the default foreground and background colors, respectively.
- `separators` - A table containing custom [separator value presets](#value-presets).
- `theme` - Either a string containing the color theme name or a table containing the colors. The theme's `fg` and `bg` values also represent the default foreground and background colors, respectively. To know more about Feline themes, take a look at the [Themes](#themes) section
- `separators` - A table containing custom [separator presets](#separator-presets).
- `force_inactive` - A table that determines which buffers should always have the inactive statusline, even when they are active. It can have 3 values inside of it, `filetypes`, `buftypes` and `bufnames`, all three of them are tables which contain Lua patterns to match against file type, buffer type and buffer name respectively.<br><br>
Default:

Expand Down Expand Up @@ -664,22 +664,60 @@ The diagnostics and LSP providers all require the Neovim built-in LSP to be conf

The diagnostics provider also provides a utility function `require('feline.providers.lsp').diagnostics_exist(type)` for checking if any diagnostics of the provided type exists. The values of `type` must be one of `'Error'`, `'Warning'`, `'Hint'` or `'Information'`.

## Value presets
## Themes

Value presets are names for colors and separators that you can use instead of the hex code or separator string, respectively.
Feline supports different themes to customize your statusline colors on the fly. A theme is a Lua table associating color names with their RGB hex codes. Feline only has one theme built-in, which is the default theme. However, it's possible to add new themes to Feline. See the [Adding new themes](#adding-new-themes) section for more info.

For your ease of use, Feline has some default color and separator values set. You can manually access them through `require('feline.defaults').colors` and `require('feline.defaults').separators` respectively. But there's a much easier way to use them, which is to just directly assign the name of the color or separator to the value, eg:
There are mainly two ways of using a theme. The first is to set the value of `theme` in the [setup function](#setup-function) to the theme name or value. The second way is through the `require('feline').use_theme` function. `use_theme` can take the theme name as an argument. For example, this is how to use the default theme:

```lua
hl = {bg = 'oceanblue'},
right_sep = 'slant_right'
require('feline').use_theme('default')
```

`use_theme` can also take the theme table directly as argument, like this:

```lua
-- Theme table
local my_theme = {
red = '#FF0000',
green = '#00FF00',
blue = '#0000FF'
}

require('feline').use_theme(my_theme)
```

### Adding new themes

If you're developing a plugin or colorscheme and wish to support Feline for that plugin / colorscheme or if you're just a user who wants to be able to quickly switch your statusline colors, you'd be glad to know that it's possible to add custom color themes for Feline. You just have to call `require('feline').add_theme` with the theme name and the colors table. Like this:

```
-- Theme table
local my_theme = {
red = '#FF0000',
green = '#00FF00',
blue = '#0000FF'
}
require('feline').add_theme('my_theme_name', my_theme)
```

Not only that, you can add your own custom colors and separators through the [setup function](#setup-function) which allows you to just use the name of the color or separator to refer to it.
The user can then later use that theme through one of the two ways mentioned above.

Below is a list of all the default value names and their values:
### Using theme colors

### Default colors
To use colors from a theme, just use the color name instead of the RGB hex code in your component's `hl` value, like this:

```lua
hl = {
bg = 'oceanblue',
fg = 'white'
}
```

### Default color theme

Feline comes with a default color theme by default, and it falls back to this theme if a color name is not found in the current theme. Here are the colors available in the default theme and their values:

| Name | Value |
| ----------- | ----------- |
Expand All @@ -697,6 +735,16 @@ Below is a list of all the default value names and their values:
| `white` | `'#FFFFFF'` |
| `yellow` | `'#E1E120'` |

## Separator presets

Instead of having to remember unicode values for separator glyphs or having to constantly copy-paste them, you can use Feline's separator presets instead. They allow you to either use Feline's [default separators](#default-separators) or your own manually defined separators (added through the [setup function](#setup-function)) by just using their name. For example:

```lua
right_sep = 'slant_right'
```

Below is a list of all the default separator names and their values:

### Default Separators

| Name | Value |
Expand Down
21 changes: 3 additions & 18 deletions lua/feline/defaults.lua
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,9 @@
-- overriding it

return {
colors = {
type = 'table',
update_default = true,
default_value = {
bg = '#1F1F23',
black = '#1B1B1B',
skyblue = '#50B0F0',
cyan = '#009090',
fg = '#D0D0D0',
green = '#60A040',
oceanblue = '#0066cc',
magenta = '#C26BDB',
orange = '#FF9000',
red = '#D10000',
violet = '#9E93E8',
white = '#FFFFFF',
yellow = '#E1E120'
}
theme = {
type = {'table', 'string'},
default_value = 'default'
},
separators = {
type = 'table',
Expand Down
57 changes: 28 additions & 29 deletions lua/feline/generator.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,6 @@ local bo = vim.bo
local api = vim.api

local feline = require('feline')
local providers = feline.providers
local colors = feline.colors
local separators = feline.separators

local M = {
-- Cached highlights
Expand All @@ -13,31 +10,31 @@ local M = {

-- Return true if any pattern in tbl matches provided value
local function find_pattern_match(tbl, val)
return next(vim.tbl_filter(function(pattern) return val:match(pattern) end, tbl))
return tbl and next(vim.tbl_filter(function(pattern) return val:match(pattern) end, tbl))
end

-- Check if current buffer is forced to have inactive statusline
local function is_forced_inactive()
local force_inactive = feline.force_inactive
local buftype = bo.buftype
local filetype = bo.filetype
local bufname = api.nvim_buf_get_name(0)

return (force_inactive.filetypes and find_pattern_match(force_inactive.filetypes, filetype)) or
(force_inactive.buftypes and find_pattern_match(force_inactive.buftypes, buftype)) or
(force_inactive.bufnames and find_pattern_match(force_inactive.bufnames, bufname))
return
find_pattern_match(feline.force_inactive.filetypes, filetype) or
find_pattern_match(feline.force_inactive.buftypes, buftype) or
find_pattern_match(feline.force_inactive.bufnames, bufname)
end

-- Check if buffer is configured to have statusline disabled
local function is_disabled()
local disable = feline.disable
local buftype = bo.buftype
local filetype = bo.filetype
local bufname = api.nvim_buf_get_name(0)

return (disable.filetypes and find_pattern_match(disable.filetypes, filetype)) or
(disable.buftypes and find_pattern_match(disable.buftypes, buftype)) or
(disable.bufnames and find_pattern_match(disable.bufnames, bufname))
return
find_pattern_match(feline.disable.filetypes, filetype) or
find_pattern_match(feline.disable.buftypes, buftype) or
find_pattern_match(feline.disable.bufnames, bufname)
end

-- Evaluate a component key if it is a function, else return the value
Expand Down Expand Up @@ -67,14 +64,18 @@ end
local function parse_hl(hl, parent_hl)
parent_hl = parent_hl or {}

hl.fg = hl.fg or parent_hl.fg or colors.fg
hl.bg = hl.bg or parent_hl.bg or colors.bg
hl.style = hl.style or parent_hl.style or 'NONE'
local fg = hl.fg or parent_hl.fg or feline.colors.fg
local bg = hl.bg or parent_hl.bg or feline.colors.bg
local style = hl.style or parent_hl.style or 'NONE'

if colors[hl.fg] then hl.fg = colors[hl.fg] end
if colors[hl.bg] then hl.bg = colors[hl.bg] end
if feline.colors[fg] then fg = feline.colors[fg] end
if feline.colors[bg] then bg = feline.colors[bg] end

return hl
return {
fg = fg,
bg = bg,
style = style
}
end

-- If highlight is a string, use it as highlight name and
Expand Down Expand Up @@ -147,15 +148,15 @@ local function parse_sep(sep, parent_bg, is_component_empty)
if is_component_empty then return '' end

str = sep
hl = {fg = parent_bg, bg = colors.bg}
hl = {fg = parent_bg, bg = feline.colors.bg}
else
if is_component_empty and not sep.always_visible then return '' end

str = evaluate_if_function(sep.str) or ''
hl = evaluate_if_function(sep.hl) or {fg = parent_bg, bg = colors.bg}
hl = evaluate_if_function(sep.hl) or {fg = parent_bg, bg = feline.colors.bg}
end

if separators[str] then str = separators[str] end
if feline.separators[str] then str = feline.separators[str] end

return string.format('%%#%s#%s', get_hlname(hl), str)
end
Expand Down Expand Up @@ -217,8 +218,8 @@ local function parse_provider(provider, component)

-- If provider is a string and its name matches the name of a registered provider, use it
if type(provider) == 'string' then
if providers[provider] then
str, icon = providers[provider](component, {})
if feline.providers[provider] then
str, icon = feline.providers[provider](component, {})
else
str = provider
end
Expand All @@ -234,13 +235,13 @@ local function parse_provider(provider, component)
"Expected 'string' for provider name, got '%s' instead",
type(provider.name)
))
elseif not providers[provider.name] then
elseif not feline.providers[provider.name] then
api.nvim_err_writeln(string.format(
"Provider with name '%s' doesn't exist",
provider.name
))
else
str, icon = providers[provider.name](component, provider.opts or {})
str, icon = feline.providers[provider.name](component, provider.opts or {})
end
end

Expand Down Expand Up @@ -364,9 +365,7 @@ end

-- Generate statusline by parsing all components and return a string
function M.generate_statusline(is_active)
local components_table = feline.components

if not components_table or is_disabled() then
if not feline.components or is_disabled() then
return ''
end

Expand All @@ -378,7 +377,7 @@ function M.generate_statusline(is_active)
statusline_type='inactive'
end

local sections = components_table[statusline_type]
local sections = feline.components[statusline_type]

if not sections then
return ''
Expand Down
Loading

0 comments on commit 47dc59e

Please sign in to comment.