diff --git a/README.md b/README.md
index 8463761..fd1a94d 100644
--- a/README.md
+++ b/README.md
@@ -11,6 +11,7 @@ for `lualine.nvim` with additional components.
- [🧩 Provided components](#provided-components)
- [ex.spellcheck](#exspellcheck)
- [ex.cwd](#excwd)
+ - [ex.location](#exlocation)
- [ex.relative_filename](#exrelative_filename)
- [ex.git.branch](#exgitbranch)
- [ex.lsp.single](#exlspsingle)
@@ -137,6 +138,34 @@ sections = {
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'` | |
+| `'%3L:%-2C'` | |
+
+
+```lua
+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.relative_filename
diff --git a/lua/lualine/components/ex/location.lua b/lua/lualine/components/ex/location.lua
new file mode 100644
index 0000000..f128857
--- /dev/null
+++ b/lua/lualine/components/ex/location.lua
@@ -0,0 +1,31 @@
+local log = require('plenary.log').new({ plugin = 'ex.location' })
+
+local Location = require('lualine.ex.component'):extend({
+ pattern = '%2C:%-3L/%T',
+})
+
+function Location:post_init()
+ self.__substitutions = {}
+ self.__pattern = string.gsub(self.options.pattern, '(%%%-?%d*[LCT]+)', function(template)
+ return string.gsub(template, '([LCT])', function(value)
+ table.insert(self.__substitutions, value)
+ return 'd'
+ end)
+ end)
+ log.debug(self.__substitutions)
+ log.debug(self.__pattern)
+end
+
+function Location:update_status()
+ local values = {
+ L = vim.fn.line('.'),
+ C = vim.fn.virtcol('.'),
+ T = vim.fn.line('$'),
+ }
+ local substitutions = vim.tbl_map(function(key)
+ return values[key]
+ end, self.__substitutions)
+ return string.format(self.__pattern, unpack(substitutions))
+end
+
+return Location
diff --git a/tests/components/location_spec.lua b/tests/components/location_spec.lua
new file mode 100644
index 0000000..f929082
--- /dev/null
+++ b/tests/components/location_spec.lua
@@ -0,0 +1,47 @@
+local l = require('tests.ex.lualine')
+local t = require('tests.ex.busted') --:ignore_all_tests()
+
+local eq = assert.are.equal
+
+local orig = {
+ line = vim.fn.line,
+ virtcol = vim.fn.virtcol,
+}
+local mock = {
+ line = {},
+ virtcol = {},
+}
+
+local component_name = 'ex.location'
+describe(component_name, function()
+ before_each(function()
+ vim.fn.line = function(arg)
+ return mock.line[arg]
+ end
+ vim.fn.virtcol = function(arg)
+ return mock.virtcol[arg]
+ end
+ end)
+
+ after_each(function()
+ vim.fn.line = orig.line
+ vim.fn.virtcol = orig.virtcol
+ end)
+
+ describe('default patter', function()
+ it('should show {line}:{column}/{total}', function()
+ mock.virtcol['.'] = 11
+ mock.line['.'] = 222
+ mock.line['$'] = 3333
+ local component = l.render_component(component_name)
+ eq('11:222/3333', component)
+ end)
+ it('should fill numbers by space', function()
+ mock.virtcol['.'] = 1
+ mock.line['.'] = 2
+ mock.line['$'] = 3
+ local component = l.render_component(component_name)
+ eq(' 1:2 /3', component)
+ end)
+ end)
+end)