Skip to content

Plugin for lualine.nvim with additional components and tools

License

Notifications You must be signed in to change notification settings

dokwork/lualine-ex

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

64 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

lualine-ex

lualine-ex ci

This is a plugin for lualine.nvim with additional components.

This is not a plugin for neovim. This is a plugin for plugin for neovim ㋡. So, it's reasonable to install it as dependency for lualine.nvim:

{
    'nvim-lualine/lualine.nvim',
    dependencies = { 
      { 'dokwork/lualine-ex' },
      { 'nvim-lua/plenary.nvim' },
      { 'kyazdani42/nvim-web-devicons' },
    }
}
use {
    'nvim-lualine/lualine.nvim',
    requires = { 
      { 'dokwork/lualine-ex' },
      { 'nvim-lua/plenary.nvim' },
      { 'kyazdani42/nvim-web-devicons' },
    }
}

It may be reasonable to use particular tag to avoid breaking changes.

Every provided component has additional options:

{
    -- The function or boolean to check is the component enabled or not:
    is_enabled = true

    -- The color for the disabled component:
    disabled_color = { fg = 'grey' }

    -- The color for the icon of the disabled component:
    disabled_icon_color = { fg = 'grey' }

    -- The different default for the option:
    draw_empty = true
}

This plugin introduces a new disabled state. This state means that a component is not active, but an icon still should be shown with disabled color. The difference between cond = false and the is_enabled = false is that in the first case a component will not be rendered at all, but in the second case only the icon with disabled_color will be shown.

You may try every component from this repo in the separate nvim instance. To do this run in terminal:

make demo component=<component name>

Where the <component name> is the same string as should be used in the lualine configuration. For example: ex.cwd.

Also, it's possible to pass a custom component options to the demo:

make demo component=<component name> component_opts='<json object>'

The <json object> should correspond to the lua table with component options. For example:

make demo component=ex.cwd component_opts='{ "depth": 1 }'

Most of the components use icons from a patched nerd font by default.

ex.spellcheck

vim.o.spell=true:   vim.o.spell=false:  

This simplest component shows an actual status of the vim.wo.spell option.

sections = {
  lualine_a = {
    {
      'ex.spellcheck',

      -- The color for the disabled component:
      disabled_color = { fg = 'grey' }

      -- The color for the icon of the disabled component:
      disabled_icon_color = { fg = 'grey' }
    }
  }
}

ex.cwd

pwd = /Users/dokwork/.local/share/nvim/lazy/lualine-ex:      

This component shows the last depth directories from the working path:

sections = {
  lualine_a = {
    {
      'ex.cwd',
      
      -- The count of directories from the current working path, if > 0 then parts will be taken from
      -- the end of the path, or from the start if {depth} < 0:
      depth = 2,

      -- The prefix which should be used when {depth} great than 0 and less than directories in the
      -- path:
      prefix = ''

      -- The count of symbols in the `cwd` after which the reduction algorith will be applied:
      -- if it > 0 and < 1 then it will be calculated as {max_length} * {vim.o.columns} for 
      -- {laststatus} == 3; and {max_length} * {vim.api.nvim_win_get_width(0)} for {laststatus} ~= 3; 
      max_length = 0.2
    }
  }
}

Reduction algorithm

The absolute value of the {depth} will be decreased until the length of the path becomes less then {max_length}.

ex.location

This component shows the current cursor position in configurable format. Comparing to the default location component, this component can show total number of lines, and may be flexibly configured.

pattern example
'%2C:%-3L/%T' ex location
'%3L:%-2C' ex location-2
sections = {
  lualine_a = {
    {
      'ex.location',
      
      -- The pattern to show the cursor position. Here three possible specifiers:
      --  'L' means 'line' - the number of the line where is the cursor now;
      --  'C' means 'column' - the number of the virtual column where is the cursor now;
      --  'T' means 'total' - the total count of lines in the current buffer;
      -- Every specifier can be used in similar maner to %d in the {string.format} function.
      -- The pattern similar to the default 'location' component is '%3L:%-2C'
      pattern = '%2C:%-3L/%T'
    }
  }
}

ex.progress

This component shows the progress in the file. It has two pre-build modes: 'percent' and 'bar'. The first one is similar to the default progress component, but in the second 'bar' mode the progress is shown as a progress bar.

mode example
'percent' ex progress-percent
'bar' ex progress-bar
sections = {
  lualine_a = {
    {
      'ex.progress',
      
      -- How to show the progress. It may be the one of two string constants:
      -- 'percent' or 'bar'. In the 'percent' mode the progress is shown as percent of the file.
      -- In the 'bar' mode it's shown as the vertical bar. Also, it can be a table with symbols
      -- which will be taken to show according to the progress, or a function, which receive three
      -- arguments: the component itself, the cursor line and total lines count in the file.
      mode = 'percent',

      -- This string will be shown when the cursor is on the first line of the file. Set `false`
      -- to turn this logic off.
      top = 'Top',

      -- This string will be shown when the cursor is on the last line of the file. Set `false`
      -- to turn this logic off.
      bottom = 'Bot'
    }
  }
}

ex.relative_filename

This component shows a filename: a file name and a path to the current file relative to the current working directory. The filename has a prefix, which shows a file's place in the file system relative to the cwd:

File path relative to cwd Options Component example
inside cwd
outside cwd external_prefix = "/..."
outside cwd, but inside $HOME

Some path may be very long and takes significant part in the statusline. It's possible to specify the {max_length} of the filename. To achieve that the follow algorithm is used:

  • every part of the path is shortened till the {shorten.length} except parts from the {shorten.exclude} list;
  • then the {shorten.length} will be repeatedly decreased until 1 or until the {max_length} will be achieved;
  • if it's not enough then the {exclude} setting will be ignored and all parts will be shortened;
  • if the result is still longer than {max_length} than only the file name will be used with the prefix {filename_only_prefix}.

Example of the shortened filename with follow options { shorten: { length = 3, exclude = { 1 } } }:

Space for component enough to show ... Component example
the whole path
the path with specified options (shorten.length = 3)
the path with shorten.length = 2
the path with shorten.length = 1
the path ignoring exclude section
only the file name

The {max_length} may be a number, or a function which receives the current component value and returns a number:

  • Every value less than 0 means that the filename never should be shortened;
  • Zero means that filename should be always shortened;
  • A value more or equal to 1 represents a length, after which the filename should be shortened;
  • A value between 0 and 1 represents a fraction of the current window width if the {laststatus} == 2, or a fraction of the terminal width.

Default configuration:

{
    -- The prefix which is used when the current file is outside cwd
    external_prefix = nil,

    -- The prefix which is used when the length of the filename after shortening
    -- is longer than {max_length}
    filename_only_prefix = '…/',

    -- The max length of the component value. It may be a number or a function.
    -- If it's function, then it will be invoked with actual value, and should 
    -- return a number:
    -- < 0          - never shorten; 
    -- 0            - always shorten; 
    -- > 0 and  < 1 - shorten when longer than {max_length} * {vim.o.columns} 
    --                for {laststatus} == 3;
    --                and shorten when longer than 
    --                {max_length} * {vim.api.nvim_win_get_width(0)} overwise; 
    -- >= 1         - shorten when longer then N symbols;
    max_length = 0.3,

    -- The configuration of the shorten algorithm.
    shorten = { 
        -- The count of letters, which will be taken from every part of the path
        lenght = 5, 
        -- The list of indexes of filename parts, which should not be shortened
        -- at all (the file name { -1 } is always excluded)
        exclude = nil 
    },
}

ex.relative_filename component doesn't provide options to show file states, because it is easily possible to do with standard approach:

-- readonly mode indicator example:
{
    '%{""}',
    draw_empty = true,
    icon = { '' },
    cond = function()
        return not vim.bo.modifiable
    end,
}

ex.git.branch

No git worktree Worktree is committed Worktree is changed

This component shows a name of a git branch for a current working directory. The color of this component depends on the state of the git worktree. The component can show different states of the git worktree:

  • changed means that at least one uncommitted change exists;
  • committed means that everything is committed, and no one tracked file is changed;
  • disabled means that the cwd is not under git control.

Default configuration:

sections = {
  lualine_a = {
    {
      'ex.git.branch',

      icon = '',

      -- The `git status` command is used to check the status of the worktree.
      -- By default, it's run in background for performance purpose, but it could lead to
      -- the wrong 'unknow' status at the first time. The `sync = true` can prevent it, 
      -- but it degrades startup time: 
      sync = false, 

      -- The colors for possible states:
      colors = {
          changed = { fg = 'orange' },
          committed = { fg = 'green' },
      },

      -- The color for the disabled component:
      disabled_color = { fg = 'grey' },

      -- The color for the icon of the disabled component:
      disabled_icon_color = { fg = 'grey' },

      -- It can be a function which receive an actual component value, and should return a number;
      -- or it can be a number:
      -- * any number >= 1 is max count of symbols in the branch name
      -- * a number between 0 and 1 means fraction of the {vim.o.columns}
      --   for {laststatus} == 3, and fraction of the {vim.api.nvim_win_get_width(0)}
      --   in other cases.
      -- When this option is defined, a component value will be cropped if it's longer then
      -- a value of this property.
      max_length = nil,

      -- Follow options actual only if {max_length} is defined:
      crop = {
        -- The string which will be used instead of cropped part.
        stub =  '',

         -- The side from which a value should be cropped. It may be 'left' or 'right'.
         -- If not specified, result depends on the component section:
         --   'right' for a|b|c
         --   'left' for x|y|z
        side = nil 
      }

      -- The {ex.crop} function is default {fmt} implementation.
      fmt = ex.crop
    }
  }
}

ex.lsp.single

No one lsp client:        lua_ls is active: 

This component shows a name and appropriate icon of the first active lsp client for the current buffer.

An icon and a color are taken from the icons table or nvim-web-devicons plugin (if it's installed). If no one icon was found for the lsp client neither in icons, nor in nvim-web-devicons, the unknown icon will be used. For the case, when no one server is run, the component is in disabled state and has the lsp_is_off icon.

An icon should be either a string or a table with following format: the [1] element must be a string with icon's symbol; the optional element color should be one of: a name of a color, or a color in #RGB format, or a table with fg color.

NOTE: the icon's property color with the type of string for any icon from the icons has different meaning comparing to usual lualine colors. It should be a name of a color not a highlight group.

sections = {
  lualine_a = {
    {
      'ex.lsp.single',

      icons = {
        -- Default icon for any unknow server:
        unknown = '?', 

        -- Default icon for a case, when no one server is run:
        lsp_is_off = '',

        -- Example of the icon for a client, which doesn't have an icon in `nvim-web-devicons`:
        ['null-ls'] = { 'N', color = 'magenta' }
      }

      -- If true then the name of the client will be ommited, and only an icon used:
      icons_only = false,

      -- The color for the disabled component:
      disabled_color = { fg = 'grey' }

      -- The color for the icon of the disabled component:
      disabled_icon_color = { fg = 'grey' }
    }
  }
}

ex.lsp.all

No one lsp client Only lua_ls is run and active Both lua_ls and vimls are run, but only vimls is active

demo

This component provides information about status of all run LSP servers. Every server has its own color and icon, which can be taken from the option icons or plugin nvim-web-devicons (if it's installed).

When some of already run servers is not active for the current buffer, it is in disabled state. The component in disabled state has a color specified in the option disabled_color.

If no one lsp client is run, the component shows only lsp_is_off icon.

The ex.lsp.all component has the same options as the ex.lsp.single component, with few additional:

sections = {
  lualine_a = {
    {
      'ex.lsp.all',

      -- Extends options from the `ex.lsp.single`

      -- If true then only clients attached to the current buffer will be shown:
      only_attached = false,

      -- If true then every closed client will be echoed:
      notify_enabled = true
      
      -- The name of highlight group which should be used in echo:
      notify_hl = 'Comment'
    }
  }
}

You may double click by this component to stop all not used lsp clients. Also, you can use the function to close not used clients outside the component (see Tools > stop_unused_clients), or change the on_click handler:

-- close on Ctrl+single click
on_click = function(clicks, button, modified)
    if modified == 'c' and clicks == 1 then
        require('lualine.ex.lsp').stop_unused_clients()
    end
end

ex.lsp.none_ls

This component shows names of the null-ls sources according to the specified query. By default, it shows names of all sources actual to the current buffer. All duplicated names are merged.

sections = {
  lualine_a = {
    {
      'ex.lsp.none_ls',

      -- The table or function that returns the table with the source query.
      -- By default it shows only actual sorces. To show all registered sources
      -- you can use just empty table:
      -- query = {}
      query = function()
        return { filetype = vim.bo.filetype }
      end,

      -- The string separator between names
      source_names_separator = ',',

      -- The color for the disabled component:
      disabled_color = { fg = 'grey' }

      -- The color for the icon of the disabled component:
      disabled_icon_color = { fg = 'grey' }
    }
  }
}

No one source: null-ls-disabled The jq and the spell sources are active for the current buffer:nulll-ls-enabled

🛠️ Tools

This plugin provide additional tools to help you create your own components. Read more details here: Tools.md.